併發7-線程池

用優雅的方式理解和使用線程池

  1. 線程池的目的
    (1)減少系統維護線程的開銷
    (2)解耦,運行和創建分開
    (3)線程可以複用

  2. 線程池的使用
    (1)接口Executor  提供方法execute(Runnable)執行線程命令
    (2)接口ExecutorService 提供方法shutdown()  啓動一次順序關閉,執行以前提交的任務,但不接受新任務

     


    Future(框架):交給我一個任務,我給你一個發票,到時候用發票取結果。
    Executors

    此包中所定義的 ExecutorExecutorServiceScheduledExecutorServiceThreadFactory 和 Callable 類的工廠和實用方法。此類支持以下各種方法:

    • 創建並返回設置有常用配置字符串的 ExecutorService 的方法。
    • 創建並返回設置有常用配置字符串的 ScheduledExecutorService 的方法。
    • 創建並返回“包裝的”ExecutorService 方法,它通過使特定於實現的方法不可訪問來禁用重新配置。
    • 創建並返回 ThreadFactory 的方法,它可將新創建的線程設置爲已知的狀態。
    • 創建並返回非閉包形式的 Callable 的方法,這樣可將其用於需要 Callable 的執行方法中。

    (3)線程池的分類
    newFixedThreadPool(int nThreads) 
              創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。

     


    newCachedThreadPool() 
              創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。(可變大小的線程池)

     


    newSingleThreadExecutor() 
              創建一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程。

     


    newScheduledThreadPool(int corePoolSize) 
              創建一個線程池,它可安排在給定延遲後運行命令或者定期地執行。

     



    (4)定義

    (5)使用

  3. 線程池的原理

    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
    

      

    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    

      

    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    

      

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return new ScheduledThreadPoolExecutor(corePoolSize);
        }
    

      鏈接

    public ScheduledThreadPoolExecutor(int corePoolSize) {
            super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
                  new DelayedWorkQueue());
        }
    

      鏈接

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
        }
    

      

    核心參數
    int corePoolSize 核心線程池的大小
    int maximumPoolSize 最大線程數量
    long keepAliveTime 線程保持活動的時間 爲什麼這裏要有保持活動時間?因爲存在覈心線程池,與線程池同生命週期(同生共死),非核心也就是最大線程數量超過核心線程數量的線程,會存在生命週期。
    TimeUnit unit 線程保持活動的時間單位
    BlockingQueue<Runnable> workQueue 任務隊列(BlockingQueue:阻塞隊列)
    defaultHandler 拒絕策略

    線程池狀態:
    private static final int COUNT_BITS = Integer.SIZE - 3;  線程數量
    private static final int CAPACITY = (1 << COUNT_BITS) - 1; 最多容量
    private static final int RUNNING = -1 << COUNT_BITS;
    private static final int SHUTDOWN = 0 << COUNT_BITS;
    private static final int STOP = 1 << COUNT_BITS;
    private static final int TIDYING = 2 << COUNT_BITS;
    private static final int TERMINATED = 3 << COUNT_BITS;

    狀態變化

    Execute方法
    int c = ctl.get();//獲取當前線程池的狀態
            if (workerCountOf(c) < corePoolSize) {//當前線程數量小於 coreSize 時創建一個新的線程運行
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {//如果當前線程處於運行狀態,並且寫入阻塞隊列成功
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))  //雙重檢查,再次獲取線程狀態;如果線程狀態變了(非運行狀態)就需要從阻塞隊列移除任務,並嘗試判斷線程是否全部執行完畢。同時執行拒絕策略。
                    reject(command);
                else if (workerCountOf(recheck) == 0)  //如果當前線程池爲空就新創建一個線程並執行。
                    addWorker(null, false);
            }
            else if (!addWorker(command, false)) //如果在第三步的判斷爲非運行狀態,嘗試新建線程,如果失敗則執行拒絕策略
                reject(command);
    }
    

      


    線程池的關閉
    pool.shutdown();
    while(!pool.isTerminated()){

    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章