線程


線程

線程的四種狀態

  • New:線程剛剛創建,還未加入線程調度
  • Runnable:就緒態,調用 start() 后,線程加入線程調度。此時,只要獲取到 CPU 時間片,就會進入運行態
  • Running:運行態,線程獲取到 CPU 時間片后,就會被 CPU 運行。可以通過 yield() 主動讓出時間片,會使得線程返回就緒態
  • Blocked:阻塞態,此時線程需要等待釋放信號才能進入就緒態,如等待用戶輸入、等待鎖被解除
  • Dead:線程結束

線程中的變量

// 獲取當前線程Thread thread = Thread.currentThread();
// 獲取線程 IDlong id = thread.getId();
// 獲取線程 Name String name = thread.getName();
// 獲取線程優先級int priority = thread.getPriority();
publicfinalstaticint MIN_PRIORITY = 1;
publicfinalstaticint NORM_PRIORITY = 5;
publicfinalstaticint MAX_PRIORITY = 10;
// 判定線程是否為守護線程boolean isDaemon = thread.isDaemon();
// 判定線程是否被中斷;被中斷會進入阻塞 Blocked 狀態boolean isInterrupted = thread.isInterrupted();
// 判定線程是否存活boolean isAlive = thread.isAlive();

創建線程的方式

  • 繼承Thread類
  • 實現Runnable接口
  • 實現Callable接口
  • 使用線程池創建
    1.submit和excute有什么區別
    submit支持實現Runnable和Callable接口的線程
    不調用Future的get()方法會吃掉異常
    excute只支持Runnable接口的現場
public class ThreadStudy {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Thread1 tread1 = new Thread1();
        tread1.setName("線程一");
        tread1.start();
        Thread thread2 = new Thread(new Thread2());
        thread2.setName("線程二");
        thread2.start();
        FutureTask<String> task = new FutureTask<String>(new Thread3());
        Thread thread3 = new Thread(task);
        thread3.setName("線程三");
        thread3.start();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        System.out.println("-----------------------");
        executorService.execute(new Thread2());
        executorService.execute(new Thread1());
        executorService.submit(new Thread3());
        Future<String> submit = executorService.submit(new Thread3());
        String result = submit.get();
        System.out.println(result);

        Executors.newCachedThreadPool();
        Executors.newSingleThreadExecutor();
        executorService.shutdown();
    }
}
class Thread1 extends Thread{
    @Override
    public void run() {
        System.out.println("這是繼承Thread創建的線程:"+Thread.currentThread().getName());
    }
}
class Thread2 implements  Runnable{
    @Override
    public void run() {
        System.out.println("這是實現Runnable創建的線程:"+Thread.currentThread().getName());
    }
}

class Thread3 implements Callable {

    @Override
    public String call() throws Exception {
        System.out.println("這是實現Callable創建的線程:"+Thread.currentThread().getName());
        return "這是實現Callable創建的線程:"+Thread.currentThread().getName();
    }
}

線程池創建的線程

public ThreadPoolExecutor(int corePoolSize, // 核心線程池大小
                            int maximumPoolSize,  // 最大線程池大小
                            long keepAliveTime,  // 線程最大空閑時間
                            TimeUnit unit,  // 時間單位
                            BlockingQueue<Runnable> workQueue, // 線程等待隊列
                            ThreadFactory threadFactory,  // 線程創建工程
                            RejectedExecutionHandler handler ) { //拒絕策列
      if (corePoolSize < 0 ||
          maximumPoolSize <= 0 ||
          maximumPoolSize < corePoolSize ||
          keepAliveTime < 0)
          throw new IllegalArgumentException();
      if (workQueue == null || threadFactory == null || handler == null)
          throw new NullPointerException();
      this.corePoolSize = corePoolSize;
      this.maximumPoolSize = maximumPoolSize;
      this.workQueue = workQueue;
      this.keepAliveTime = unit.toNanos(keepAliveTime);
      this.threadFactory = threadFactory;
      this.handler = handler;
  }
  • newFixedThreadPool

    • 參數分析:核心線程數和最大線程數相同,線程等待隊列無限大
    • 使用場景:Web服務器瞬間削峰,持續高峰情況需要注意隊列阻塞
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
  • newCacheThreadPool

    • 參數分析:核心線程池為0,最大線程數無限大,線程最大空閑時間60秒
    • 使用場景:快速處理大量耗時較短的任務,如Netty的NIO接受請求時,可使用CachedThreadPool。
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>(),
                                  threadFactory);
}
  • newSchedulThreadPool

參數分析:傳入核心線程

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}
  • newSingeThreadExecutor

參數分析:依靠FinalizableDelegatedExecutorService執行操作

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
}
static class FinalizableDelegatedExecutorService
    extends DelegatedExecutorService {
    FinalizableDelegatedExecutorService(ExecutorService executor) {
        super(executor);
    }
    protected void finalize() {
        super.shutdown();
    }
}
  • newSingThreadSchedulExecutor

參數:線程工廠

public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1, threadFactory));
}
static class DelegatedScheduledExecutorService
        extends DelegatedExecutorService
        implements ScheduledExecutorService {
    private final ScheduledExecutorService e;
    DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
        super(executor);
        e = executor;
    }
    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
        return e.schedule(command, delay, unit);
    }
    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
        return e.schedule(callable, delay, unit);
    }
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
        return e.scheduleAtFixedRate(command, initialDelay, period, unit);
    }
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
        return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
    }
}

自定義線程池

public class ThreadTest {

    public static void main(String[] args) throws InterruptedException, IOException {
        int corePoolSize = 2;
        int maximumPoolSize = 4;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        ThreadFactory threadFactory = new NameTreadFactory();
        RejectedExecutionHandler handler = new MyIgnorePolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
                workQueue, threadFactory, handler);
        executor.prestartAllCoreThreads(); // 預啟動所有核心線程
        
        for (int i = 1; i <= 10; i++) {
            MyTask task = new MyTask(String.valueOf(i));
            executor.execute(task);
        }

        System.in.read(); //阻塞主線程
    }

    static class NameTreadFactory implements ThreadFactory {

        private final AtomicInteger mThreadNum = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement());
            System.out.println(t.getName() + " has been created");
            return t;
        }
    }

    public static class MyIgnorePolicy implements RejectedExecutionHandler {

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            doLog(r, e);
        }

        private void doLog(Runnable r, ThreadPoolExecutor e) {
            // 可做日志記錄等
            System.err.println( r.toString() + " rejected");
//          System.out.println("completedTaskCount: " + e.getCompletedTaskCount());
        }
    }

    static class MyTask implements Runnable {
        private String name;

        public MyTask(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                System.out.println(this.toString() + " is running!");
                Thread.sleep(3000); //讓任務執行慢點
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return "MyTask [name=" + name + "]";
        }
    }
}

線程池的大小

IO密集型
CPU密集型
Runtime.getRuntime().availableProcessors():獲取CPU的核數

結論

總結,通過自定義線程池,我們可以更好的讓線程池為我們所用,更加適應我的實際場景。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM