並發7-線程池
阿新 • • 發佈:2019-03-31
int 分開 queue tex single ret imu executor lock
用優雅的方式理解和使用線程池
- 線程池的目的
(1)減少系統維護線程的開銷
(2)解耦,運行和創建分開
(3)線程可以復用 - 線程池的使用
(1)接口Executor 提供方法execute(Runnable)執行線程命令
(2)接口ExecutorService 提供方法shutdown() 啟動一次順序關閉,執行以前提交的任務,但不接受新任務
Future(框架):交給我一個任務,我給你一個發票,到時候用發票取結果。
Executors
此包中所定義的
Executor
、ExecutorService
、ScheduledExecutorService
ThreadFactory
和Callable
類的工廠和實用方法。此類支持以下各種方法:- 創建並返回設置有常用配置字符串的
ExecutorService
的方法。 - 創建並返回設置有常用配置字符串的
ScheduledExecutorService
的方法。 - 創建並返回“包裝的”ExecutorService 方法,它通過使特定於實現的方法不可訪問來禁用重新配置。
- 創建並返回
ThreadFactory
的方法,它可將新創建的線程設置為已知的狀態。 - 創建並返回非閉包形式的
Callable
的方法,這樣可將其用於需要 Callable 的執行方法中。
(3)線程池的分類newFixedThreadPool(int nThreads)
創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。
newCachedThreadPool()
創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。(可變大小的線程池)
newSingleThreadExecutor()
創建一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程。
newScheduledThreadPool(int corePoolSize)
創建一個線程池,它可安排在給定延遲後運行命令或者定期地執行。
(4)定義
(5)使用 - 創建並返回設置有常用配置字符串的
- 線程池的原理
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()){
}
並發7-線程池