Java并發(fā)編程(十一)線程池的使用
1.new Thread的弊端如下:
- a. 每次new Thread新建對象性能差。
- b. 線程缺乏統(tǒng)一管理,可能無限制新建線程,相互之間競爭,及可能占用過多系統(tǒng)資源導致死機或oom。
- c. 缺乏更多功能,如定時執(zhí)行、定期執(zhí)行、線程中斷。
相比new Thread,Java提供的四種線程池的好處在于:
- a.重用線程池中存在的線程,避免因為線程的大量創(chuàng)建和銷毀所帶來的性能開銷 ,完成一項任務(wù)的時間T=創(chuàng)建線程的時間+在線程中執(zhí)行任務(wù)的時間+線程銷毀的時間, 而線程池的出現(xiàn)可以大大減少創(chuàng)建線程的時間和線程銷毀的時間,從而提高app的性能
- b.能有限的控制線程池的最大并發(fā)數(shù),并且大量的線程互相搶占資源而導致的阻塞現(xiàn)象
- c.對線程池中線程進行有效的跟進,當我們不需要處理的時候可以將它shutdow掉,并提供定時執(zhí)行以及制定間隔循環(huán)執(zhí)行,
2、Java 線程池
Java通過Executors提供四種線程池,分別為:
CachedThreadPool創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。在線程空閑60秒后終止線程。
FixedThreadPool 創(chuàng)建一個定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會在隊列中等待。
ScheduledThreadPool 創(chuàng)建一個定長線程池,支持定時及周期性任務(wù)執(zhí)行。
SingleThreadExecutor 創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。
Executors類用于管理Thread對象,簡化并發(fā)過程,我們可以看到FixedThreadPool的創(chuàng)建過程:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
顯然這四種線程池方法都是返回實現(xiàn)了ExecutorService接口的ThreadPoolExecutor。當然我們也可以直接用ThreadPoolExecutor來自定義更靈活的線程池。
我們先看看ThreadPoolExecutor的構(gòu)建參數(shù):
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
當池子大小小于corePoolSize就新建線程,并處理請求,當池子大小大于corePoolSize,把請求放入workQueue中,池子里的空閑線程就去從workQueue中取任務(wù)并處理,當workQueue放不下新入的任務(wù)時,新建線程入池,并處理請求,如果池子大小撐到了maximumPoolSize就用RejectedExecutionHandler來做拒絕處理。另外,當池子的線程數(shù)大于corePoolSize的時候,多余的線程會等待keepAliveTime長的時間,如果無請求可處理就自行銷毀

接下來我們來看看CachedThreadPool:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
CachedThreadPool在程序執(zhí)行時會創(chuàng)建與所需數(shù)量相同的線程,然后在它回收舊線程時停止創(chuàng)建新線程,因此是Executor的首選,只有當這種方式會引發(fā)問題,或者不符合業(yè)務(wù)需要時才采用另外的三種Executor提供的線程池
SingleThreadExecutor 就是線程數(shù)量為1的FixedThreadPool,如果向SingleThreadExecutor提交多個任務(wù),那么這些任務(wù)會排隊,每個任務(wù)都會在下個任務(wù)開始之前就結(jié)束,所有任務(wù)都用一個線程,并且按照提交的順序執(zhí)行。
線程池用于線程數(shù)量比較多時的場景,如果只開啟2,3個線程就用線程池,顯然會極度的浪費資源
浙公網(wǎng)安備 33010602011771號