自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

看完這篇,再也不怕面試官問(wèn)我線程池了

開發(fā) 前端
在實(shí)際使用中,線程是很占用系統(tǒng)資源的,如果對(duì)線程管理不完善的話很容易導(dǎo)致系統(tǒng)問(wèn)題。

[[397999]]

本文轉(zhuǎn)載自微信公眾號(hào)「牧小農(nóng)」,作者牧小農(nóng)。轉(zhuǎn)載本文請(qǐng)聯(lián)系牧小農(nóng)公眾號(hào)。

一、為什么需要線程池

在實(shí)際使用中,線程是很占用系統(tǒng)資源的,如果對(duì)線程管理不完善的話很容易導(dǎo)致系統(tǒng)問(wèn)題。因此,在大多數(shù)并發(fā)框架中都會(huì)使用線程池來(lái)管理線程,使用線程池管理線程主要有如下好處:

  • 1、使用線程池可以重復(fù)利用已有的線程繼續(xù)執(zhí)行任務(wù),避免線程在創(chuàng)建和銷毀時(shí)造成的消耗
  • 2、由于沒(méi)有線程創(chuàng)建和銷毀時(shí)的消耗,可以提高系統(tǒng)響應(yīng)速度
  • 3、通過(guò)線程可以對(duì)線程進(jìn)行合理的管理,根據(jù)系統(tǒng)的承受能力調(diào)整可運(yùn)行線程數(shù)量的大小等

二、工作原理

流程圖:

線程池執(zhí)行所提交的任務(wù)過(guò)程:

  • 1、比如我們?cè)O(shè)置核心線程池的數(shù)量為30個(gè),不管有沒(méi)有用戶連接,我們總是保證30個(gè)連接,這個(gè)就是核心線程數(shù),這里的核心線程數(shù)不一定是30你可以根據(jù)你的需求、業(yè)務(wù)和并發(fā)訪問(wèn)量來(lái)設(shè)置,先判斷線程池中核心線程池所有的線程是否都在執(zhí)行任務(wù),如果不是,則新創(chuàng)建一個(gè)線程執(zhí)行剛提交的任務(wù),否則,核心線程池中所有的線程都在執(zhí)行任務(wù),則進(jìn)入第2步;
  • 2、如果我們核心線程數(shù)的30個(gè)數(shù)量已經(jīng)滿了,就需要到阻塞隊(duì)列中去查看,判斷當(dāng)前阻塞隊(duì)列是否已滿,如果未滿,則將提交的任務(wù)放置在阻塞隊(duì)列中等待執(zhí)行;否則,則進(jìn)入第3步;
  • 3、判斷線程池中所有的線程是否都在執(zhí)行任務(wù),如果沒(méi)有,則創(chuàng)建一個(gè)新的線程來(lái)執(zhí)行任務(wù),否則,則交給飽和策略進(jìn)行處理,也叫拒絕策略,等下我們會(huì)有詳細(xì)的介紹

注意: 這里有一個(gè)核心線程數(shù)和一個(gè)線程池?cái)?shù)量,這兩個(gè)是不同的概念,核心線程數(shù)代表我能夠維護(hù)常用的線程開銷,而線程池?cái)?shù)量則代表我最大能夠創(chuàng)建的線程數(shù),例如在我們農(nóng)村每家每戶都有吃水的井,基本上有半井深的水就可以維持我們的日常生活的使用,這里的半井深的水就好比我們的核心線程數(shù),還有一半的容量是我們井能夠容納的最大水資源了,超過(guò)了就不行,水就會(huì)漫出來(lái),這個(gè)就類似于我們的線程池的數(shù)量,不知道這里說(shuō)明大家是否能夠更好的進(jìn)行理解

三、線程池的分類

1.newCachedThreadPool: 創(chuàng)建一個(gè)可根據(jù)需要?jiǎng)?chuàng)建新線程的線程池,但是在以前構(gòu)造的線程可用時(shí)講重用它們,并在需要時(shí)使用提供的ThreadFactory 創(chuàng)建新線程

特征:

(1) 線程池中的數(shù)量沒(méi)有固定,可以達(dá)到最大值(Integer.MAX_VALUE=2147483647)

(2) 線程池中的線程可進(jìn)行緩存重復(fù)利用和回收(回收默認(rèn)時(shí)間為1分鐘)

(3) 當(dāng)線程池中,沒(méi)有可用線程,會(huì)重新創(chuàng)建一個(gè)線程

2.newFixedThreadPool: 創(chuàng)建一個(gè)可重用固定線程數(shù)的線程池,以共享的無(wú)界隊(duì)列方式來(lái)運(yùn)行這些線程,在任意點(diǎn),在大多數(shù)nThreads線程會(huì)處于處理任務(wù)的活動(dòng)狀態(tài)。如果在所有線程處于活動(dòng)狀態(tài)時(shí)提交附件任務(wù),則在有可用線程之前,附件任務(wù)將在隊(duì)列中等待,如果在關(guān)閉前的執(zhí)行期間由于失敗而導(dǎo)致任何線程終止,那么一個(gè)新線程將代替它執(zhí)行后續(xù)的任務(wù)(如果需要)。在某個(gè)線程被顯式關(guān)閉之前,池中的線程將一直存在

特征:

(1) 線程池中的線程處于一定的量,可以很好的控制線程的并發(fā)量

(2) 線程可以重復(fù)被使用,在顯示關(guān)閉之前,都將一直存在

(3) 超過(guò)一定量的線程被提交時(shí)需在隊(duì)列中等待

3.newSingleThreadExecutor: 創(chuàng)建一個(gè)使用單個(gè) worker 線程的Executor ,以無(wú)界隊(duì)列方式來(lái)運(yùn)行該線程。(注意,如果因?yàn)樵陉P(guān)閉前的執(zhí)行期間出現(xiàn)失敗而終止了此單個(gè)線程,那么如果需要,一個(gè)新線程將代替它執(zhí)行后續(xù)的任務(wù))。可保證順序地執(zhí)行各個(gè)任務(wù),并且在任意給定的時(shí)間不會(huì)有多個(gè)線程是活動(dòng)的,與其他等效的 newFixedThreadPool(1)不同,可保證無(wú)需重新配置此方法所返回的執(zhí)行程序即可使用其他的線程

特征:

(1) 線程池中最多執(zhí)行一個(gè)線程,之后提交的線程將會(huì)排在隊(duì)列中以此執(zhí)行

4.newSingleThreadScheduledExecutor: 創(chuàng)建一個(gè)單線程執(zhí)行程序,它可安排在給定延遲后運(yùn)行命令或者定期執(zhí)行

特征:

(1) 線程池中最多執(zhí)行一個(gè)線程,之后提交的線程活動(dòng)將會(huì)排在隊(duì)列中依次執(zhí)行

(2) 可定時(shí)或者延遲執(zhí)行線程活動(dòng)

5.newScheduledThreadPool: 創(chuàng)建一個(gè)線程池,它可安排在給定延遲后運(yùn)行命令或者定期的執(zhí)行

特征:

(1) 線程池中具有執(zhí)行數(shù)量的線程,即便是空線程也將保留

(2) 可定時(shí)或者延遲執(zhí)行線程活動(dòng)

6.newWorkStealingPool: 創(chuàng)建一個(gè)帶并行級(jí)別的線程池,并行級(jí)別決定了同一時(shí)刻最多有多少個(gè)線程在執(zhí)行,如不傳并行級(jí)別參數(shù),將默認(rèn)為當(dāng)前系統(tǒng)的CPU個(gè)數(shù)

我們可以在開發(fā)工具中搜索一個(gè)叫Executors的類,在里面我們可以看到我們上面所有的使用方法

四、ThreadPoolExecutor

線程工具類——Task :

  1. public class Task implements Runnable{ 
  2.     @Override 
  3.     public void run() { 
  4.         try { 
  5.             //休眠1秒 
  6.             Thread.sleep(1000); 
  7.         } catch (InterruptedException e) { 
  8.             e.printStackTrace(); 
  9.         } 
  10.         //輸出線程名 
  11.         System.out.println(Thread.currentThread().getName()+"-------running"); 
  12.     } 

4.1 newCachedThreadPool

源碼實(shí)現(xiàn):

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

案例:

  1. public class CacheThreadPoolDemo { 
  2.     public static void main(String[] args) { 
  3.         ExecutorService executorService = Executors.newCachedThreadPool(); 
  4.         for (int i = 0; i < 20; i++) { 
  5.             //提交任務(wù) 
  6.             executorService.execute(new Task()); 
  7.         } 
  8.         //啟動(dòng)有序關(guān)閉,其中先前提交的任務(wù)將被執(zhí)行,但不會(huì)接受任何新任務(wù) 
  9.         executorService.shutdown(); 
  10.     } 

結(jié)果輸出:

從開始到結(jié)束我們總共輸出了20個(gè)(pool-1-thread-1到pool-1-thread-20)線程

  1. pool-1-thread-2-------running 
  2. pool-1-thread-6-------running 
  3. pool-1-thread-1-------running 
  4. pool-1-thread-3-------running 
  5. pool-1-thread-5-------running 
  6. pool-1-thread-4-------running 
  7. pool-1-thread-7-------running 
  8. pool-1-thread-11-------running 
  9. pool-1-thread-9-------running 
  10. pool-1-thread-10-------running 
  11. pool-1-thread-17-------running 
  12. pool-1-thread-15-------running 
  13. pool-1-thread-18-------running 
  14. pool-1-thread-16-------running 
  15. pool-1-thread-8-------running 
  16. pool-1-thread-20-------running 
  17. pool-1-thread-13-------running 
  18. pool-1-thread-19-------running 
  19. pool-1-thread-14-------running 
  20. pool-1-thread-12-------running 

4.2 newFixedThreadPool

源碼實(shí)現(xiàn):

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

案例:

  1. public class FixedThreadPoolDemo { 
  2.     public static void main(String[] args) { 
  3.         //創(chuàng)建線程池,最多允許五個(gè)線程執(zhí)行 
  4.         ExecutorService executorService = Executors.newFixedThreadPool(5); 
  5.         for (int i = 0; i < 20; i++) { 
  6.             //提交任務(wù) 
  7.             executorService.execute(new Task()); 
  8.         } 
  9.         //啟動(dòng)有序關(guān)閉,其中先前提交的任務(wù)將被執(zhí)行,但不會(huì)接受任何新任務(wù) 
  10.         executorService.shutdown(); 
  11.     } 

輸出結(jié)果:

我們可以看到其中的線程是每五個(gè)(pool-1-thread-1到pool-1-thread-5)一執(zhí)行,在當(dāng)前執(zhí)行的線程運(yùn)行中,最多允許五個(gè)線程進(jìn)行執(zhí)行

  1. pool-1-thread-4-------running 
  2. pool-1-thread-2-------running 
  3. pool-1-thread-1-------running 
  4. pool-1-thread-3-------running 
  5. pool-1-thread-5-------running 
  6. pool-1-thread-4-------running 
  7. pool-1-thread-5-------running 
  8. pool-1-thread-3-------running 
  9. pool-1-thread-2-------running 
  10. pool-1-thread-1-------running 
  11. pool-1-thread-4-------running 
  12. pool-1-thread-2-------running 
  13. pool-1-thread-1-------running 
  14. pool-1-thread-3-------running 
  15. pool-1-thread-5-------running 
  16. pool-1-thread-4-------running 
  17. pool-1-thread-5-------running 
  18. pool-1-thread-2-------running 
  19. pool-1-thread-1-------running 
  20. pool-1-thread-3-------running 

4.3 newSingleThreadExecutor

源碼實(shí)現(xiàn):

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

案例:

  1. public class SingleThreadPoolDemo { 
  2.     public static void main(String[] args) { 
  3.         ExecutorService executorService = Executors.newSingleThreadExecutor(); 
  4.         for (int i = 0; i < 20; i++) { 
  5.             //提交任務(wù) 
  6.             executorService.execute(new Task()); 
  7.         } 
  8.         //啟動(dòng)有序關(guān)閉,其中先前提交的任務(wù)將被執(zhí)行,但不會(huì)接受任何新任務(wù) 
  9.         executorService.shutdown(); 
  10.     } 

結(jié)果輸出:

我們可以看到每次都是線程1輸出結(jié)果

  1. pool-1-thread-1-------running 
  2. pool-1-thread-1-------running 
  3. pool-1-thread-1-------running 
  4. pool-1-thread-1-------running 
  5. pool-1-thread-1-------running 
  6. pool-1-thread-1-------running 
  7. pool-1-thread-1-------running 
  8. pool-1-thread-1-------running 
  9. pool-1-thread-1-------running 
  10. pool-1-thread-1-------running 
  11. pool-1-thread-1-------running 
  12. pool-1-thread-1-------running 
  13. pool-1-thread-1-------running 
  14. pool-1-thread-1-------running 
  15. pool-1-thread-1-------running 
  16. pool-1-thread-1-------running 
  17. pool-1-thread-1-------running 
  18. pool-1-thread-1-------running 
  19. pool-1-thread-1-------running 
  20. pool-1-thread-1-------running 

五、ScheduledThreadPoolExecutor

5.1 newScheduledThreadPool

案例:

  1.     public static void main(String[] args) { 
  2.         ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3); 
  3. //        for (int i = 0; i < 20; i++) { 
  4.         System.out.println(System.currentTimeMillis()); 
  5.             scheduledExecutorService.schedule(new Runnable() { 
  6.                 @Override 
  7.                 public void run() { 
  8.                     System.out.println("延遲三秒執(zhí)行"); 
  9.                     System.out.println(System.currentTimeMillis()); 
  10.                 } 
  11.             },3, TimeUnit.SECONDS); 
  12. //        } 
  13.  
  14.         scheduledExecutorService.shutdown(); 
  15.     } 
  16.  

輸出結(jié)果:

  1. 1606744468814 
  2. 延遲三秒執(zhí)行 
  3. 1606744471815 

5.2 newSingleThreadScheduledExecutor

案例:

  1.  public static void main(String[] args) { 
  2.         ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); 
  3.             scheduledExecutorService.scheduleAtFixedRate(new Runnable() { 
  4.                 int i = 1; 
  5.                 @Override 
  6.                 public void run() { 
  7.                     System.out.println(i); 
  8.                     i++; 
  9.                 } 
  10.             },0,1, TimeUnit.SECONDS); 
  11. //        scheduledExecutorService.shutdown(); 
  12.     } 

輸出結(jié)果:

六、線程池的生命周期

一般來(lái)說(shuō)線程池只有兩種狀態(tài),一種是Running,一種是TERMINATED,圖中間的都是過(guò)渡狀態(tài)

Running:能接受新提交的任務(wù),并且也能處理阻塞隊(duì)列中的任務(wù)

SHUTDOWN:關(guān)閉狀態(tài),不再接受新提交的任務(wù),但卻可以繼續(xù)處理阻塞隊(duì)列中已保存的任務(wù)

STOP:不能接受新任務(wù),也不處理隊(duì)列中的任務(wù),會(huì)中斷正在處理任務(wù)的線程

TIDYING:如果所有的任務(wù)都已終止了,workerCount(有效線程數(shù))為0.線程池進(jìn)入該狀態(tài)后會(huì)調(diào)用terminated()方法進(jìn)入TERMINATED狀態(tài)

TERMINATED:在terminated()方法執(zhí)行完成后進(jìn)入該狀態(tài),默認(rèn)terminated()方法中什么也沒(méi)有做

七、線程池的創(chuàng)建

7.1 Executors 源碼

  1. public ThreadPoolExecutor(int corePoolSize, 
  2.                            int maximumPoolSize, 
  3.                            long keepAliveTime, 
  4.                            TimeUnit unit, 
  5.                            BlockingQueue<Runnable> workQueue, 
  6.                            ThreadFactory threadFactory, 
  7.                            RejectedExecutionHandler handler) 

7.2 參數(shù)說(shuō)明

corePoolSize:核心線程池的大小

maximumPoolSize:線程池能創(chuàng)建線程的最大個(gè)數(shù)

keepAliveTime:空閑線程存活時(shí)間

unit:時(shí)間單位,為keepAliveTime指定時(shí)間單位

workQueue:阻塞隊(duì)列,用于保存任務(wù)的阻塞隊(duì)列

threadFactory:創(chuàng)建線程的工程類

handler:飽和策略(拒絕策略)

八、阻塞隊(duì)列

ArrayBlockingQueue:

基于數(shù)組的阻塞隊(duì)列實(shí)現(xiàn),在ArrayBlockingQueue內(nèi)部,維護(hù)了一個(gè)定長(zhǎng)數(shù)組,以便緩存隊(duì)列中的數(shù)據(jù)對(duì)象,這是-個(gè)常用的阻塞隊(duì)列,除了一個(gè)定長(zhǎng)數(shù)組外,ArrayBlockingQueue內(nèi)部還保存著兩個(gè)整形變量,分別標(biāo)識(shí)著隊(duì)列的頭部和尾部在數(shù)組中的位置。

ArrayBlockingQueue在生產(chǎn)者放入數(shù)據(jù)和消費(fèi)者獲取數(shù)據(jù),都是共用同一個(gè)鎖對(duì)象,由此也意味著兩者無(wú)法真正并行運(yùn)行,這點(diǎn)尤其不同于LinkedBlockingQueue;按照實(shí)現(xiàn)原理來(lái)分析,ArrayBlockingQueue完全可以采用分離鎖,從而實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者操作的完全并行運(yùn)行。Doug Lea之所以沒(méi)這樣去做,也許是因?yàn)锳rrayBlockingQueue的數(shù)據(jù)寫入和獲取操作已經(jīng)足夠輕巧,以至于引入獨(dú)立的鎖機(jī)制,除了給代碼帶來(lái)額外的復(fù)雜性外,其在性能上完全占不到任何便宜。

ArrayBlockingQueue和LinkedBlockingQueue間還有一個(gè)明顯的不同之處在于,前者在插入或刪除元素時(shí)不會(huì)產(chǎn)生或銷毀任何額外的對(duì)象實(shí)例,而后者則會(huì)生成一個(gè)額外的Node對(duì)象。這在長(zhǎng)時(shí)間內(nèi)需要高效并發(fā)地處理大批量數(shù)據(jù)的系統(tǒng)中,其對(duì)于GC的影響還是存在一定的區(qū)別。而在創(chuàng)建ArrayBlockingQueue時(shí),我們還可以控制對(duì)象的內(nèi)部鎖是否采用公平鎖,默認(rèn)采用非公平鎖。

LinkedBlockingQueue:

基于鏈表的阻塞隊(duì)列,同ArrayListBlockingQueue類似,其內(nèi)部也維持著一個(gè)數(shù)據(jù)緩沖隊(duì)列(該隊(duì)列由一個(gè)鏈表構(gòu)成),當(dāng)生產(chǎn)者往隊(duì)列中放入一個(gè)數(shù)據(jù)時(shí),隊(duì)列會(huì)從生產(chǎn)者手中獲取數(shù)據(jù),并緩存在隊(duì)列內(nèi)部,而生產(chǎn)者立即返回;只有當(dāng)隊(duì)列緩沖區(qū)達(dá)到最大值緩存容量時(shí)( LinkedBlockingQueue可以通過(guò)構(gòu)造函數(shù)指定該值),才會(huì)阻塞生產(chǎn)者隊(duì)列,直到消費(fèi)者從隊(duì)列中消費(fèi)掉─份數(shù)據(jù),生產(chǎn)者線程會(huì)被喚醒,反之對(duì)打于消費(fèi)者這端的處理也基于同樣的原理。而

LinkedBlockingQueue之所以能夠高效的處理并發(fā)數(shù)據(jù),還因?yàn)槠鋵?duì)于生產(chǎn)者端和消費(fèi)者端分別采用了獨(dú)立的鎖來(lái)控制數(shù)據(jù)同步,這也意味著在高并發(fā)的情況下生產(chǎn)者和消費(fèi)者可以并行地操作隊(duì)列中的數(shù)據(jù),以此來(lái)提高整個(gè)隊(duì)列的并發(fā)性能。

DelayQueue:

DelayQueue中的元素只有當(dāng)其指定的延遲時(shí)間到了,才能夠從隊(duì)列中獲取到該元素。DelayQueue是一個(gè)沒(méi)有大小限制的隊(duì)列,因此往隊(duì)列中插入數(shù)據(jù)的操作(生產(chǎn)者)永遠(yuǎn)不會(huì)被阻塞,而只有獲取數(shù)據(jù)的操作(消費(fèi)者)才會(huì)被阻塞。

使用場(chǎng)景︰

DelayQueue使用場(chǎng)景較少,但都相當(dāng)巧妙,常見(jiàn)的例子比如使用一個(gè)DelayQueue來(lái)管理一個(gè)超時(shí)未響應(yīng)的連接隊(duì)列。

PriorityBlockingQueue:

基于優(yōu)先級(jí)的阻塞隊(duì)列(優(yōu)先級(jí)的判斷通過(guò)構(gòu)造函數(shù)傳入的Compator對(duì)象來(lái)決定),但需要注意的是

PriorityBlockingQueue并不會(huì)阻塞數(shù)據(jù)生產(chǎn)者,而只會(huì)在沒(méi)有可消費(fèi)的數(shù)據(jù)時(shí),阻塞數(shù)據(jù)的消費(fèi)者。因此使用的時(shí)候要特別注意,生產(chǎn)者生產(chǎn)數(shù)據(jù)的速度絕對(duì)不能快于消費(fèi)者消費(fèi)數(shù)據(jù)的速度,否則時(shí)間一長(zhǎng),會(huì)最終耗盡所有的可用堆內(nèi)存空間。在實(shí)現(xiàn)PriorityBlockingQueue時(shí),內(nèi)部控制線程同步的鎖采用的是公平鎖。

SynchronousQueue:

一種無(wú)緩沖的等待隊(duì)列,類似于無(wú)中介的直接交易,有點(diǎn)像原始社會(huì)中的生產(chǎn)者和消費(fèi)者,生產(chǎn)者拿著產(chǎn)品去集市銷售給產(chǎn)品的最終消費(fèi)者,而消費(fèi)者必須親自去集市找到所要商品的直接生產(chǎn)者,如果一方?jīng)]有找到合適的目標(biāo),那么對(duì)不起,大家都在集市等待。相對(duì)于有緩沖的BlockingQueue來(lái)說(shuō),少了一個(gè)中間經(jīng)銷商的環(huán)節(jié)(緩沖區(qū)),如果有經(jīng)銷商,生產(chǎn)者直接把產(chǎn)品批發(fā)給經(jīng)銷商,而無(wú)需在意經(jīng)銷商最終會(huì)將這些產(chǎn)品賣給那些消費(fèi)者,由于經(jīng)銷商可以庫(kù)存一部分商品,因此相對(duì)于直接交易模式,總體來(lái)說(shuō)采用中間經(jīng)銷商的模式會(huì)吞吐量高一些(可以批量買賣)﹔但另一方面,又因?yàn)榻?jīng)銷商的引入,使得產(chǎn)品從生產(chǎn)者到消費(fèi)者中間增加了額外的交易環(huán)節(jié),單個(gè)產(chǎn)品的及時(shí)響應(yīng)性能可能會(huì)降低。

聲明一個(gè)SynchronousQueue有兩種不同的方式,它們之間有著不太一樣的行為。公平模式和非公平模式的區(qū)別:如果采用公平模式:SynchronousQueue會(huì)采用公平鎖,并配合一個(gè)FIFO隊(duì)列來(lái)阻塞多余的生產(chǎn)者和消費(fèi)者,從而體系整體的公平策略;

但如果是非公平模式 ( SynchronousQueue默認(rèn)) : SynchronousQueue采用非公平鎖,同時(shí)配合一個(gè)LIFO隊(duì)列來(lái)管理多余的生產(chǎn)者和消費(fèi)者,而后一種模式,如果生產(chǎn)者和消費(fèi)者的處理速度有差距,則很容易出現(xiàn)饑渴的情況,即可能有某些生產(chǎn)者或者是消費(fèi)者的數(shù)據(jù)永遠(yuǎn)都得不到處理。

注意:

arrayblockingqueue和linkedblockqueue的區(qū)別:1.隊(duì)列中鎖的實(shí)現(xiàn)不同

1、ArrayBlockingQueue實(shí)現(xiàn)的隊(duì)列中的鎖是沒(méi)有分離的,即生產(chǎn)和消費(fèi)用的是同一個(gè)鎖;

LinkedBlockingQueue實(shí)現(xiàn)的隊(duì)列中的鎖是分離的,即生產(chǎn)用的是putLock,消費(fèi)是takeLock2.隊(duì)列大小初始化方式不同

2、ArrayBlockingQueue實(shí)現(xiàn)的隊(duì)列中必須指定隊(duì)列的大小;

LinkedBlockingQueue實(shí)現(xiàn)的隊(duì)列中可以不指定隊(duì)列的大小,但是默認(rèn)是Integer.MAX_VALUE

九、拒絕策略

ThreadPoolExecutor.AbortPolicy(系統(tǒng)默認(rèn)):丟棄任務(wù)并拋出RejectedExecutionException異常,讓你感知到任務(wù)被拒絕了,我們可以根據(jù)業(yè)務(wù)邏輯選擇重試或者放棄提交等策略

ThreadPoolExecutor.DiscardPolicy: 也是丟棄任務(wù),但是不拋出異常,相對(duì)而言存在一定的風(fēng)險(xiǎn),因?yàn)槲覀兲峤坏臅r(shí)候根本不知道這個(gè)任務(wù)會(huì)被丟棄,可能造成數(shù)據(jù)丟失。

ThreadPoolExecutor.DiscardOldestPolicy: 丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過(guò)程),通常是存活時(shí)間最長(zhǎng)的任務(wù),它也存在一定的數(shù)據(jù)丟失風(fēng)險(xiǎn)

ThreadPoolExecutor.CallerRunsPolicy: 由調(diào)用線程處理該任務(wù)

十、execute()和submit()方法

10.1 execute方法執(zhí)行邏輯

 

  • 如果當(dāng)前運(yùn)行的線程少于corePoolSize,則會(huì)創(chuàng)建新的線程來(lái)執(zhí)行新的任務(wù);
  • 如果運(yùn)行的線程個(gè)數(shù)等于或者大于corePoolSize,則會(huì)將提交的任務(wù)存放到阻塞隊(duì)列workQueue中;
  • 如果當(dāng)前workQueue隊(duì)列已滿的話,則會(huì)創(chuàng)建新的線程來(lái)執(zhí)行任務(wù);
  • 如果線程個(gè)數(shù)已經(jīng)超過(guò)了maximumPoolSize,則會(huì)使用飽和策略RejectedExecutionHandler來(lái)進(jìn)行處理

10.2 Submit

submit是基方法Executor.execute(Runnable)的延伸,通過(guò)創(chuàng)建并返回一個(gè)Future類對(duì)象可用于取消執(zhí)行和/或等待完成。

十一、線程池的關(guān)閉

 

  • 關(guān)閉線程池,可以通過(guò)shutdown和shutdownNow兩個(gè)方法
  • 原理:遍歷線程池中的所有線程,然后依次中斷
  • 1、shutdownNow首先將線程池的狀態(tài)設(shè)置為STOP,然后嘗試停止所有的正在執(zhí)行和未執(zhí)行任務(wù)的線程,并返回等待執(zhí)行任務(wù)的列表;
  • 2、shutdown只是將線程池的狀態(tài)設(shè)置為SHUTDOWN狀態(tài),然后中斷所有沒(méi)有正在執(zhí)行任務(wù)的線程

 

責(zé)任編輯:武曉燕 來(lái)源: 牧小農(nóng)
相關(guān)推薦

2022-04-01 07:52:42

JavaScript防抖節(jié)流

2020-11-24 07:48:32

React

2021-08-10 18:36:02

Express原理面試

2020-10-20 09:12:57

axios核心原理

2022-08-27 13:49:36

ES7promiseresolve

2020-10-23 09:26:57

React-Redux

2021-03-03 12:19:20

原型原型鏈JavaScript

2023-11-28 17:49:51

watch?computed?性能

2020-10-15 12:52:46

SpringbootJava編程語(yǔ)言

2022-10-31 11:10:49

Javavolatile變量

2024-02-26 00:00:00

Docker容器

2021-04-22 07:49:51

Vue3Vue2.xVue3.x

2020-04-16 08:22:11

HTTPS加解密協(xié)議

2024-04-02 09:45:27

線程池Executors開發(fā)

2020-01-15 08:06:28

HTTP超文本傳輸協(xié)議網(wǎng)絡(luò)協(xié)議

2020-02-03 17:22:34

垃圾回收原理種類

2020-03-14 09:17:55

HTTPS網(wǎng)絡(luò)協(xié)議HTTP

2023-02-28 17:27:02

分庫(kù)分表中間件

2019-02-14 10:13:42

網(wǎng)絡(luò)故障RIPIGRP

2021-12-02 08:19:06

MVCC面試數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)