<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          線程池的7種創(chuàng)建方式,強(qiáng)烈推薦你用它...

          共 10851字,需瀏覽 22分鐘

           ·

          2021-02-02 00:18

          根據(jù)摩爾定律所說:集成電路上可容納的晶體管數(shù)量每 18 個(gè)月翻一番,因此 CPU 上的晶體管數(shù)量會(huì)越來越多。

          但隨著時(shí)間的推移,集成電路上可容納的晶體管數(shù)量已趨向飽和,摩爾定律也漸漸失效,因此多核 CPU 逐漸變?yōu)橹髁鳎c之相對(duì)應(yīng)的多線程編程也開始變得普及和流行起來,這當(dāng)然也是很久之前的事了,對(duì)于現(xiàn)在而言多線程編程已經(jīng)成為程序員必備的職業(yè)技能了,那接下來我們就來盤一盤“線程池”這個(gè)多線程編程中最重要的話題。

          什么是線程池?

          線程池(ThreadPool)是一種基于池化思想管理和使用線程的機(jī)制。它是將多個(gè)線程預(yù)先存儲(chǔ)在一個(gè)“池子”內(nèi),當(dāng)有任務(wù)出現(xiàn)時(shí)可以避免重新創(chuàng)建和銷毀線程所帶來性能開銷,只需要從“池子”內(nèi)取出相應(yīng)的線程執(zhí)行對(duì)應(yīng)的任務(wù)即可。

          池化思想在計(jì)算機(jī)的應(yīng)用也比較廣泛,比如以下這些:

          • 內(nèi)存池(Memory Pooling):預(yù)先申請(qǐng)內(nèi)存,提升申請(qǐng)內(nèi)存速度,減少內(nèi)存碎片。
          • 連接池(Connection Pooling):預(yù)先申請(qǐng)數(shù)據(jù)庫連接,提升申請(qǐng)連接的速度,降低系統(tǒng)的開銷。
          • 實(shí)例池(Object Pooling):循環(huán)使用對(duì)象,減少資源在初始化和釋放時(shí)的昂貴損耗。

          線程池的優(yōu)勢(shì)主要體現(xiàn)在以下4點(diǎn):

          1. 降低資源消耗:通過池化技術(shù)重復(fù)利用已創(chuàng)建的線程,降低線程創(chuàng)建和銷毀造成的損耗。
          2. 提高響應(yīng)速度:任務(wù)到達(dá)時(shí),無需等待線程創(chuàng)建即可立即執(zhí)行。
          3. 提高線程的可管理性:線程是稀缺資源,如果無限制創(chuàng)建,不僅會(huì)消耗系統(tǒng)資源,還會(huì)因?yàn)榫€程的不合理分布導(dǎo)致資源調(diào)度失衡,降低系統(tǒng)的穩(wěn)定性。使用線程池可以進(jìn)行統(tǒng)一的分配、調(diào)優(yōu)和監(jiān)控。
          4. 提供更多更強(qiáng)大的功能:線程池具備可拓展性,允許開發(fā)人員向其中增加更多的功能。比如延時(shí)定時(shí)線程池ScheduledThreadPoolExecutor,就允許任務(wù)延期執(zhí)行或定期執(zhí)行。

          同時(shí)阿里巴巴在其《Java開發(fā)手冊(cè)》中也強(qiáng)制規(guī)定:線程資源必須通過線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程

          說明:線程池的好處是減少在創(chuàng)建和銷毀線程上所消耗的時(shí)間以及系統(tǒng)資源的開銷,解決資源不足的問題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者“過度切換”的問題。

          知道了什么是線程池以及為什要用線程池之后,我們?cè)賮砜丛趺从镁€程池。

          線程池使用

          線程池的創(chuàng)建方法總共有 7 種,但總體來說可分為 2 類:

          • 一類是通過?ThreadPoolExecutor?創(chuàng)建的線程池;
          • 另一個(gè)類是通過?Executors?創(chuàng)建的線程池。


          線程池的創(chuàng)建方式總共包含以下 7 種(其中 6 種是通過?Executors?創(chuàng)建的,1 種是通過?ThreadPoolExecutor?創(chuàng)建的):

          1. Executors.newFixedThreadPool:創(chuàng)建一個(gè)固定大小的線程池,可控制并發(fā)的線程數(shù),超出的線程會(huì)在隊(duì)列中等待;
          2. Executors.newCachedThreadPool:創(chuàng)建一個(gè)可緩存的線程池,若線程數(shù)超過處理所需,緩存一段時(shí)間后會(huì)回收,若線程數(shù)不夠,則新建線程;
          3. Executors.newSingleThreadExecutor:創(chuàng)建單個(gè)線程數(shù)的線程池,它可以保證先進(jìn)先出的執(zhí)行順序;
          4. Executors.newScheduledThreadPool:創(chuàng)建一個(gè)可以執(zhí)行延遲任務(wù)的線程池;
          5. Executors.newSingleThreadScheduledExecutor:創(chuàng)建一個(gè)單線程的可以執(zhí)行延遲任務(wù)的線程池;
          6. Executors.newWorkStealingPool:創(chuàng)建一個(gè)搶占式執(zhí)行的線程池(任務(wù)執(zhí)行順序不確定)【JDK 1.8 添加】。
          7. ThreadPoolExecutor:最原始的創(chuàng)建線程池的方式,它包含了 7 個(gè)參數(shù)可供設(shè)置,后面會(huì)詳細(xì)講。

          單線程池的意義從以上代碼可以看出 newSingleThreadExecutor 和 newSingleThreadScheduledExecutor 創(chuàng)建的都是單線程池,那么單線程池的意義是什么呢?答:雖然是單線程池,但提供了工作隊(duì)列,生命周期管理,工作線程維護(hù)等功能。

          那接下來我們來看每種線程池創(chuàng)建的具體使用。

          1.FixedThreadPool

          創(chuàng)建一個(gè)固定大小的線程池,可控制并發(fā)的線程數(shù),超出的線程會(huì)在隊(duì)列中等待。

          使用示例如下:

          public?static?void?fixedThreadPool()?{
          ????//?創(chuàng)建?2?個(gè)數(shù)據(jù)級(jí)的線程池
          ????ExecutorService?threadPool?=?Executors.newFixedThreadPool(2);

          ????//?創(chuàng)建任務(wù)
          ????Runnable?runnable?=?new?Runnable()?{
          ????????@Override
          ????????public?void?run()?{
          ????????????System.out.println("任務(wù)被執(zhí)行,線程:"?+?Thread.currentThread().getName());
          ????????}
          ????};

          ????//?線程池執(zhí)行任務(wù)(一次添加?4?個(gè)任務(wù))
          ????//?執(zhí)行任務(wù)的方法有兩種:submit?和?execute
          ????threadPool.submit(runnable);??//?執(zhí)行方式?1:submit
          ????threadPool.execute(runnable);?//?執(zhí)行方式?2:execute
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          }

          執(zhí)行結(jié)果如下:

          如果覺得以上方法比較繁瑣,還用更簡(jiǎn)單的使用方法,如下代碼所示:

          public?static?void?fixedThreadPool()?{
          ????//?創(chuàng)建線程池
          ????ExecutorService?threadPool?=?Executors.newFixedThreadPool(2);
          ????//?執(zhí)行任務(wù)
          ????threadPool.execute(()?->?{
          ????????System.out.println("任務(wù)被執(zhí)行,線程:"?+?Thread.currentThread().getName());
          ????});
          }

          2.CachedThreadPool

          創(chuàng)建一個(gè)可緩存的線程池,若線程數(shù)超過處理所需,緩存一段時(shí)間后會(huì)回收,若線程數(shù)不夠,則新建線程。

          使用示例如下:

          public?static?void?cachedThreadPool()?{
          ????//?創(chuàng)建線程池
          ????ExecutorService?threadPool?=?Executors.newCachedThreadPool();
          ????//?執(zhí)行任務(wù)
          ????for?(int?i?=?0;?i?10;?i++)?{
          ????????threadPool.execute(()?->?{
          ????????????System.out.println("任務(wù)被執(zhí)行,線程:"?+?Thread.currentThread().getName());
          ????????????try?{
          ????????????????TimeUnit.SECONDS.sleep(1);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????}
          ????????});
          ????}
          }

          執(zhí)行結(jié)果如下:從上述結(jié)果可以看出,線程池創(chuàng)建了 10 個(gè)線程來執(zhí)行相應(yīng)的任務(wù)。

          3.SingleThreadExecutor

          創(chuàng)建單個(gè)線程數(shù)的線程池,它可以保證先進(jìn)先出的執(zhí)行順序。

          使用示例如下:

          public?static?void?singleThreadExecutor()?{
          ????//?創(chuàng)建線程池
          ????ExecutorService?threadPool?=?Executors.newSingleThreadExecutor();
          ????//?執(zhí)行任務(wù)
          ????for?(int?i?=?0;?i?10;?i++)?{
          ????????final?int?index?=?i;
          ????????threadPool.execute(()?->?{
          ????????????System.out.println(index?+?":任務(wù)被執(zhí)行");
          ????????????try?{
          ????????????????TimeUnit.SECONDS.sleep(1);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????}
          ????????});
          ????}
          }

          執(zhí)行結(jié)果如下:

          4.ScheduledThreadPool

          創(chuàng)建一個(gè)可以執(zhí)行延遲任務(wù)的線程池。

          使用示例如下:

          public?static?void?scheduledThreadPool()?{
          ????//?創(chuàng)建線程池
          ????ScheduledExecutorService?threadPool?=?Executors.newScheduledThreadPool(5);
          ????//?添加定時(shí)執(zhí)行任務(wù)(1s?后執(zhí)行)
          ????System.out.println("添加任務(wù),時(shí)間:"?+?new?Date());
          ????threadPool.schedule(()?->?{
          ????????System.out.println("任務(wù)被執(zhí)行,時(shí)間:"?+?new?Date());
          ????????try?{
          ????????????TimeUnit.SECONDS.sleep(1);
          ????????}?catch?(InterruptedException?e)?{
          ????????}
          ????},?1,?TimeUnit.SECONDS);
          }

          執(zhí)行結(jié)果如下:從上述結(jié)果可以看出,任務(wù)在 1 秒之后被執(zhí)行了,符合我們的預(yù)期。

          5.SingleThreadScheduledExecutor

          創(chuàng)建一個(gè)單線程的可以執(zhí)行延遲任務(wù)的線程池。

          使用示例如下:

          public?static?void?SingleThreadScheduledExecutor()?{
          ????//?創(chuàng)建線程池
          ????ScheduledExecutorService?threadPool?=?Executors.newSingleThreadScheduledExecutor();
          ????//?添加定時(shí)執(zhí)行任務(wù)(2s?后執(zhí)行)
          ????System.out.println("添加任務(wù),時(shí)間:"?+?new?Date());
          ????threadPool.schedule(()?->?{
          ????????System.out.println("任務(wù)被執(zhí)行,時(shí)間:"?+?new?Date());
          ????????try?{
          ????????????TimeUnit.SECONDS.sleep(1);
          ????????}?catch?(InterruptedException?e)?{
          ????????}
          ????},?2,?TimeUnit.SECONDS);
          }

          執(zhí)行結(jié)果如下:從上述結(jié)果可以看出,任務(wù)在 2 秒之后被執(zhí)行了,符合我們的預(yù)期。

          6.newWorkStealingPool

          創(chuàng)建一個(gè)搶占式執(zhí)行的線程池(任務(wù)執(zhí)行順序不確定),注意此方法只有在 JDK 1.8+ 版本中才能使用。

          使用示例如下:

          public?static?void?workStealingPool()?{
          ????//?創(chuàng)建線程池
          ????ExecutorService?threadPool?=?Executors.newWorkStealingPool();
          ????//?執(zhí)行任務(wù)
          ????for?(int?i?=?0;?i?10;?i++)?{
          ????????final?int?index?=?i;
          ????????threadPool.execute(()?->?{
          ????????????System.out.println(index?+?"?被執(zhí)行,線程名:"?+?Thread.currentThread().getName());
          ????????});
          ????}
          ????//?確保任務(wù)執(zhí)行完成
          ????while?(!threadPool.isTerminated())?{
          ????}
          }

          執(zhí)行結(jié)果如下:從上述結(jié)果可以看出,任務(wù)的執(zhí)行順序是不確定的,因?yàn)樗菗屨际綀?zhí)行的。

          7.ThreadPoolExecutor

          最原始的創(chuàng)建線程池的方式,它包含了 7 個(gè)參數(shù)可供設(shè)置。

          使用示例如下:

          public?static?void?myThreadPoolExecutor()?{
          ????//?創(chuàng)建線程池
          ????ThreadPoolExecutor?threadPool?=?new?ThreadPoolExecutor(5,?10,?100,?TimeUnit.SECONDS,?new?LinkedBlockingQueue<>(10));
          ????//?執(zhí)行任務(wù)
          ????for?(int?i?=?0;?i?10;?i++)?{
          ????????final?int?index?=?i;
          ????????threadPool.execute(()?->?{
          ????????????System.out.println(index?+?"?被執(zhí)行,線程名:"?+?Thread.currentThread().getName());
          ????????????try?{
          ????????????????Thread.sleep(1000);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????????e.printStackTrace();
          ????????????}
          ????????});
          ????}
          }

          執(zhí)行結(jié)果如下:

          ThreadPoolExecutor 參數(shù)介紹

          ThreadPoolExecutor 最多可以設(shè)置 7 個(gè)參數(shù),如下代碼所示:

          ?public?ThreadPoolExecutor(int?corePoolSize,
          ???????????????????????????int?maximumPoolSize,
          ???????????????????????????long?keepAliveTime,
          ???????????????????????????TimeUnit?unit,
          ???????????????????????????BlockingQueue?workQueue,
          ???????????????????????????ThreadFactory?threadFactory,
          ???????????????????????????RejectedExecutionHandler?handler)
          ?
          {
          ?????//?省略...
          ?}

          7 個(gè)參數(shù)代表的含義如下:

          參數(shù) 1:corePoolSize

          核心線程數(shù),線程池中始終存活的線程數(shù)。

          參數(shù) 2:maximumPoolSize

          最大線程數(shù),線程池中允許的最大線程數(shù),當(dāng)線程池的任務(wù)隊(duì)列滿了之后可以創(chuàng)建的最大線程數(shù)。

          參數(shù) 3:keepAliveTime

          最大線程數(shù)可以存活的時(shí)間,當(dāng)線程中沒有任務(wù)執(zhí)行時(shí),最大線程就會(huì)銷毀一部分,最終保持核心線程數(shù)量的線程。

          參數(shù) 4:unit:

          單位是和參數(shù) 3 存活時(shí)間配合使用的,合在一起用于設(shè)定線程的存活時(shí)間 ,參數(shù) keepAliveTime 的時(shí)間單位有以下 7 種可選:

          • TimeUnit.DAYS:天
          • TimeUnit.HOURS:小時(shí)
          • TimeUnit.MINUTES:分
          • TimeUnit.SECONDS:秒
          • TimeUnit.MILLISECONDS:毫秒
          • TimeUnit.MICROSECONDS:微妙
          • TimeUnit.NANOSECONDS:納秒

          參數(shù) 5:workQueue

          一個(gè)阻塞隊(duì)列,用來存儲(chǔ)線程池等待執(zhí)行的任務(wù),均為線程安全,它包含以下 7 種類型:

          • ArrayBlockingQueue:一個(gè)由數(shù)組結(jié)構(gòu)組成的有界阻塞隊(duì)列。
          • LinkedBlockingQueue:一個(gè)由鏈表結(jié)構(gòu)組成的有界阻塞隊(duì)列。
          • SynchronousQueue:一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列,即直接提交給線程不保持它們。
          • PriorityBlockingQueue:一個(gè)支持優(yōu)先級(jí)排序的無界阻塞隊(duì)列。
          • DelayQueue:一個(gè)使用優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)的無界阻塞隊(duì)列,只有在延遲期滿時(shí)才能從中提取元素。
          • LinkedTransferQueue:一個(gè)由鏈表結(jié)構(gòu)組成的無界阻塞隊(duì)列。與SynchronousQueue類似,還含有非阻塞方法。
          • LinkedBlockingDeque:一個(gè)由鏈表結(jié)構(gòu)組成的雙向阻塞隊(duì)列。

          較常用的是?LinkedBlockingQueue?和?Synchronous,線程池的排隊(duì)策略與?BlockingQueue?有關(guān)。

          參數(shù) 6:threadFactory

          線程工廠,主要用來創(chuàng)建線程,默認(rèn)為正常優(yōu)先級(jí)、非守護(hù)線程。

          參數(shù) 7:handler

          拒絕策略,拒絕處理任務(wù)時(shí)的策略,系統(tǒng)提供了 4 種可選:

          • AbortPolicy:拒絕并拋出異常。
          • CallerRunsPolicy:使用當(dāng)前調(diào)用的線程來執(zhí)行此任務(wù)。
          • DiscardOldestPolicy:拋棄隊(duì)列頭部(最舊)的一個(gè)任務(wù),并執(zhí)行當(dāng)前任務(wù)。
          • DiscardPolicy:忽略并拋棄當(dāng)前任務(wù)。

          默認(rèn)策略為?AbortPolicy

          線程池的執(zhí)行流程

          ThreadPoolExecutor 關(guān)鍵節(jié)點(diǎn)的執(zhí)行流程如下:

          • 當(dāng)線程數(shù)小于核心線程數(shù)時(shí),創(chuàng)建線程。
          • 當(dāng)線程數(shù)大于等于核心線程數(shù),且任務(wù)隊(duì)列未滿時(shí),將任務(wù)放入任務(wù)隊(duì)列。
          • 當(dāng)線程數(shù)大于等于核心線程數(shù),且任務(wù)隊(duì)列已滿:若線程數(shù)小于最大線程數(shù),創(chuàng)建線程;若線程數(shù)等于最大線程數(shù),拋出異常,拒絕任務(wù)。

          線程池的執(zhí)行流程如下圖所示:

          線程拒絕策略

          我們來演示一下 ThreadPoolExecutor 的拒絕策略的觸發(fā),我們使用?DiscardPolicy? 的拒絕策略,它會(huì)忽略并拋棄當(dāng)前任務(wù)的策略,實(shí)現(xiàn)代碼如下:

          public?static?void?main(String[]?args)?{
          ????//?任務(wù)的具體方法
          ????Runnable?runnable?=?new?Runnable()?{
          ????????@Override
          ????????public?void?run()?{
          ????????????System.out.println("當(dāng)前任務(wù)被執(zhí)行,執(zhí)行時(shí)間:"?+?new?Date()?+
          ???????????????????????????????"?執(zhí)行線程:"?+?Thread.currentThread().getName());
          ????????????try?{
          ????????????????//?等待?1s
          ????????????????TimeUnit.SECONDS.sleep(1);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????????e.printStackTrace();
          ????????????}
          ????????}
          ????};
          ????//?創(chuàng)建線程,線程的任務(wù)隊(duì)列的長(zhǎng)度為?1
          ????ThreadPoolExecutor?threadPool?=?new?ThreadPoolExecutor(1,?1,
          ???????????????????????????????????????????????????????????100,?TimeUnit.SECONDS,?new?LinkedBlockingQueue<>(1),
          ???????????????????????????????????????????????????????????new?ThreadPoolExecutor.DiscardPolicy());
          ????//?添加并執(zhí)行?4?個(gè)任務(wù)
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          }

          我們創(chuàng)建了一個(gè)核心線程數(shù)和最大線程數(shù)都為 1 的線程池,并且給線程池的任務(wù)隊(duì)列設(shè)置為 1,這樣當(dāng)我們有 2 個(gè)以上的任務(wù)時(shí)就會(huì)觸發(fā)拒絕策略,執(zhí)行的結(jié)果如下圖所示:從上述結(jié)果可以看出只有兩個(gè)任務(wù)被正確執(zhí)行了,其他多余的任務(wù)就被舍棄并忽略了。其他拒絕策略的使用類似,這里就不一一贅述了。

          自定義拒絕策略

          除了 Java 自身提供的 4 種拒絕策略之外,我們也可以自定義拒絕策略,示例代碼如下:

          public?static?void?main(String[]?args)?{
          ????//?任務(wù)的具體方法
          ????Runnable?runnable?=?new?Runnable()?{
          ????????@Override
          ????????public?void?run()?{
          ????????????System.out.println("當(dāng)前任務(wù)被執(zhí)行,執(zhí)行時(shí)間:"?+?new?Date()?+
          ???????????????????????????????"?執(zhí)行線程:"?+?Thread.currentThread().getName());
          ????????????try?{
          ????????????????//?等待?1s
          ????????????????TimeUnit.SECONDS.sleep(1);
          ????????????}?catch?(InterruptedException?e)?{
          ????????????????e.printStackTrace();
          ????????????}
          ????????}
          ????};
          ????//?創(chuàng)建線程,線程的任務(wù)隊(duì)列的長(zhǎng)度為?1
          ????ThreadPoolExecutor?threadPool?=?new?ThreadPoolExecutor(1,?1,
          ???????????????????????????????????????????????????????????100,?TimeUnit.SECONDS,?new?LinkedBlockingQueue<>(1),
          ???????????????????????????????????????????????????????????new?RejectedExecutionHandler()?{
          ???????????????????????????????????????????????????????????????@Override
          ???????????????????????????????????????????????????????????????public?void?rejectedExecution(Runnable?r,?ThreadPoolExecutor?executor)?{
          ???????????????????????????????????????????????????????????????????//?執(zhí)行自定義拒絕策略的相關(guān)操作
          ???????????????????????????????????????????????????????????????????System.out.println("我是自定義拒絕策略~");
          ???????????????????????????????????????????????????????????????}
          ???????????????????????????????????????????????????????????});
          ????//?添加并執(zhí)行?4?個(gè)任務(wù)
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          ????threadPool.execute(runnable);
          }

          程序的執(zhí)行結(jié)果如下:

          究竟選用哪種線程池?

          經(jīng)過以上的學(xué)習(xí)我們對(duì)整個(gè)線程池也有了一定的認(rèn)識(shí)了,那究竟該如何選擇線程池呢?

          我們來看下阿里巴巴《Java開發(fā)手冊(cè)》給我們的答案:

          【強(qiáng)制】線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。

          說明:Executors 返回的線程池對(duì)象的弊端如下:

          1) FixedThreadPool 和 SingleThreadPool:允許的請(qǐng)求隊(duì)列長(zhǎng)度為 Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致 OOM。

          2)CachedThreadPool:允許的創(chuàng)建線程數(shù)量為 Integer.MAX_VALUE,可能會(huì)創(chuàng)建大量的線程,從而導(dǎo)致 OOM。

          所以綜上情況所述,我們推薦使用?ThreadPoolExecutor?的方式進(jìn)行線程池的創(chuàng)建,因?yàn)檫@種創(chuàng)建方式更可控,并且更加明確了線程池的運(yùn)行規(guī)則,可以規(guī)避一些未知的風(fēng)險(xiǎn)。

          總結(jié)

          本文我們介紹了線程池的 7 種創(chuàng)建方式,其中最推薦使用的是?ThreadPoolExecutor?的方式進(jìn)行線程池的創(chuàng)建,ThreadPoolExecutor?最多可以設(shè)置 7 個(gè)參數(shù),當(dāng)然設(shè)置 5 個(gè)參數(shù)也可以正常使用,ThreadPoolExecutor?當(dāng)任務(wù)過多(處理不過來)時(shí)提供了 4 種拒絕策略,當(dāng)然我們也可以自定義拒絕策略,希望本文的內(nèi)容能幫助到你。原創(chuàng)不易,覺得不錯(cuò)就點(diǎn)個(gè)贊再走吧!

          參考 & 鳴謝

          https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html

          https://www.cnblogs.com/pcheng/p/13540619.html


          往期推薦

          Spring Boot整合Shiro,兩種方式實(shí)戰(zhàn)總結(jié)(含源碼)

          面試管:如何找出字符串中無重復(fù)最長(zhǎng)子串?

          不解釋,全網(wǎng)最全Shiro認(rèn)證與授權(quán)原理分析

          如何將一個(gè)項(xiàng)目同時(shí)提交到GitHub和Gitee(碼云)上

          還在親手寫Filter進(jìn)行權(quán)限校驗(yàn)?嘗試一下Shiro吧



          如果你覺得這篇文章不錯(cuò),那么,下篇通常會(huì)更好。關(guān)注一下【公眾號(hào)】或添加微信好友(微信號(hào):541075754),都是OK的。

          一篇文章就看透技術(shù)本質(zhì)的人,
          ? 和花一輩子都看不清的人,
          ? 注定是截然不同的搬磚生涯。
          ▲?長(zhǎng)按關(guān)注”程序新視界“,洞察技術(shù)內(nèi)幕
          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费三级片网址 | 一级片在线观看视频 | 成人在线无码视频 | 国产 在线观看免费视频 | 日韩欧美一级片在线 |