Java多線程ThreadPoolExecutor詳解
前言:
根據(jù)ThreadPoolExecutor的構(gòu)造方法,JDK提供了很多工廠方法來創(chuàng)建各種用途的線程池.
1 newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
說明:
- 核心線程數(shù) == 最大線程數(shù)(沒有救急線程被創(chuàng)建),因此也無需超時時間
- 阻塞隊列是無界的,可以放任意數(shù)量的任務(wù)(最大為Integer.MAX_VALUE)
適用于 任務(wù)量一已知,相對耗時的任務(wù)
2 newCachedThreadPool
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
說明:
- 核心線程數(shù)是 0, 最大線程數(shù)是 Integer.MAX_VALUE,救急線程的空閑生存時間是 60s
- 全部都是救急線程(60s 后可以回收)
- 救急線程可以無限創(chuàng)建(最大是Integer.MAX_VALUE)
- 隊列采用了 SynchronousQueue 實現(xiàn)特點是,它沒有容量,沒有線程來取是放不進(jìn)去的(一手交錢、一手交 貨)
如下案例:
SynchronousQueue<Integer> integers = new SynchronousQueue<>(); new Thread(() -> { try { log.debug("putting {} ", 1); integers.put(1); log.debug("{} putted...", 1); log.debug("putting...{} ", 2); integers.put(2); log.debug("{} putted...", 2); } catch (InterruptedException e) { e.printStackTrace(); } },"t1").start(); sleep(1); new Thread(() -> { try { log.debug("taking {}", 1); integers.take(); } catch (InterruptedException e) { e.printStackTrace(); } },"t2").start(); sleep(1); new Thread(() -> { try { log.debug("taking {}", 2); integers.take(); } catch (InterruptedException e) { e.printStackTrace(); } },"t3").start(); /* 運(yùn)行結(jié)果: 11:48:15.500 c.TestSynchronousQueue [t1] - putting 1 11:48:16.500 c.TestSynchronousQueue [t2] - taking 1 11:48:16.500 c.TestSynchronousQueue [t1] - 1 putted... 11:48:16.500 c.TestSynchronousQueue [t1] - putting...2 11:48:17.502 c.TestSynchronousQueue [t3] - taking 2 11:48:17.503 c.TestSynchronousQueue [t1] - 2 putted... */
整個線程池表現(xiàn)為線程數(shù)會根據(jù)任務(wù)量不斷增長,沒有上限,當(dāng)任務(wù)執(zhí)行完畢,空閑 1分鐘后釋放線程。
適用于 任務(wù)數(shù)比較密集,但每個任務(wù)執(zhí)行時間較短的情況
3 newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
希望多個任務(wù)排隊執(zhí)行。線程數(shù)固定為 1,任務(wù)數(shù)多于 1 時,會放入無界隊列排隊。任務(wù)執(zhí)行完畢,這唯一的線程也不會被釋放.
與其他線程區(qū)別:
- 自己創(chuàng)建一個單線程串行執(zhí)行任務(wù),如果任務(wù)執(zhí)行失敗而終止那么沒有任何補(bǔ)救措施,而線程池還會新建一 個線程,保證池的正常工作
- Executors.newSingleThreadExecutor() 線程個數(shù)始終為1,不能修改
- FinalizableDelegatedExecutorService 應(yīng)用的是裝飾器模式,只對外暴露了 ExecutorService 接口,因此不能調(diào)用 ThreadPoolExecutor 中特有的方法.
- Executors.newFixedThreadPool(1) 初始時為1,以后還可以修改
- 對外暴露的是 ThreadPoolExecutor 對象,可以強(qiáng)轉(zhuǎn)后調(diào)用 setCorePoolSize 等方法進(jìn)行修改
4 提交任務(wù)
// 執(zhí)行任務(wù) void execute(Runnable command); // 提交任務(wù) task,用返回值 Future 獲得任務(wù)執(zhí)行結(jié)果 <T> Future<T> submit(Callable<T> task); // 提交 tasks 中所有任務(wù) <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; // 提交 tasks 中所有任務(wù),帶超時時間 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; // 提交 tasks 中所有任務(wù),哪個任務(wù)先成功執(zhí)行完畢,返回此任務(wù)執(zhí)行結(jié)果,其它任務(wù)取消 <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; // 提交 tasks 中所有任務(wù),哪個任務(wù)先成功執(zhí)行完畢,返回此任務(wù)執(zhí)行結(jié)果,其它任務(wù)取消,帶超時時間 <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
上述都是提供的提交任務(wù)的方法,根據(jù)不同的業(yè)務(wù)場景需求,選擇對應(yīng)的提交方法.
5 關(guān)閉線程池
shutdown
/* 線程池狀態(tài)變?yōu)?SHUTDOWN - 不會接收新任務(wù) - 但已提交任務(wù)會執(zhí)行完 - 此方法不會阻塞調(diào)用線程的執(zhí)行 */ void shutdown();
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 修改線程池狀態(tài) advanceRunState(SHUTDOWN); // 僅會打斷空閑線程 interruptIdleWorkers(); onShutdown(); // 擴(kuò)展點 ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } // 嘗試終結(jié)(沒有運(yùn)行的線程可以立刻終結(jié),如果還有運(yùn)行的線程也不會等) tryTerminate(); }
shutdownNow
/* 線程池狀態(tài)變?yōu)?STOP - 不會接收新任務(wù) - 會將隊列中的任務(wù)返回 - 并用 interrupt 的方式中斷正在執(zhí)行的任務(wù) */ List<Runnable> shutdownNow();
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 修改線程池狀態(tài) advanceRunState(STOP); // 打斷所有線程 interruptWorkers(); // 獲取隊列中剩余任務(wù) tasks = drainQueue(); } finally { mainLock.unlock(); } // 嘗試終結(jié) tryTerminate(); return tasks; }
其他打斷方法
// 不在 RUNNING 狀態(tài)的線程池,此方法就返回 true boolean isShutdown(); // 線程池狀態(tài)是否是 TERMINATED boolean isTerminated(); // 調(diào)用 shutdown 后,由于調(diào)用線程并不會等待所有任務(wù)運(yùn)行結(jié)束,因此如果它想在線程池 TERMINATED 后做些事 情,可以利用此方法等待 boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
到此這篇關(guān)于Java多線程ThreadPoolExecutor詳解的文章就介紹到這了,更多相關(guān)Java ThreadPoolExecutor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java線程池?ThreadPoolExecutor?詳解
- Java線程池ThreadPoolExecutor源碼深入分析
- java高并發(fā)ThreadPoolExecutor類解析線程池執(zhí)行流程
- java高并發(fā)ScheduledThreadPoolExecutor與Timer區(qū)別
- 徹底搞懂java并發(fā)ThreadPoolExecutor使用
- Java多線程編程基石ThreadPoolExecutor示例詳解
- 源碼分析Java中ThreadPoolExecutor的底層原理
- 一文搞懂Java的ThreadPoolExecutor原理
- 一文弄懂Java中ThreadPoolExecutor
相關(guān)文章
springboot如何統(tǒng)一設(shè)置時區(qū)
這篇文章主要介紹了springboot如何統(tǒng)一設(shè)置時區(qū)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01Java中生成隨機(jī)數(shù)的實現(xiàn)方法總結(jié)
這篇文章主要介紹了Java中生成隨機(jī)數(shù)的實現(xiàn)方法總結(jié),其中多線程并發(fā)的實現(xiàn)方式尤為exciting,需要的朋友可以參考下2015-11-11java網(wǎng)絡(luò)編程學(xué)習(xí)java聊天程序代碼分享
java聊天程序代碼分享,大家參考使用吧2013-12-12