<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>

          Java多線程-線程池的使用

          共 3480字,需瀏覽 7分鐘

           ·

          2021-01-21 20:46

          ? 作者?|??阿墩

          來源 |??urlify.cn/beeAn2

          線程池的優(yōu)點

          • 線程頻繁的創(chuàng)建=>銷毀=>創(chuàng)建對系統(tǒng)對開銷很大,使用線程池可以避免重復的開銷

          • 方便復用,提高相應速度

          • 線程的創(chuàng)建于執(zhí)行完全分開,方便維護,降低耦合

          線程池的實現(xiàn)原理

          池化技術

          一說到線程池自然就會想到池化技術。

          其實所謂池化技術,就是把一些能夠復用的東西放到池中,避免重復創(chuàng)建、銷毀的開銷,從而極大提高性能。

          常見池化技術的例如:

          • 線程池

          • 內存池

          • 連接池

          Java中的實現(xiàn)

          官方接口

          JDK 1.5 推出了三大API用來創(chuàng)建線程:

          • Executors.newCachedThreadPool():無限線程池(最大21億)

          • Executors.newFixedThreadPool(nThreads):固定大小的線程池

          • Executors.newSingleThreadExecutor():單個線程的線程池

          這三個API的底層其實都是由同一個類實現(xiàn)的:ThreadPoolExecutor?類

          public?static?ExecutorService?newCachedThreadPool()?{
          ??return?new?ThreadPoolExecutor(0,?Integer.MAX_VALUE,
          ????????????????????????????????60L,?TimeUnit.SECONDS,
          ????????????????????????????????new?SynchronousQueue());
          }
          public?static?ExecutorService?newFixedThreadPool(int?nThreads)?{
          ??return?new?ThreadPoolExecutor(nThreads,?nThreads,
          ????????????????????????????????0L,?TimeUnit.MILLISECONDS,
          ????????????????????????????????new?LinkedBlockingQueue());
          }
          public?static?ExecutorService?newSingleThreadExecutor()?{
          ??return?new?FinalizableDelegatedExecutorService
          ????(new?ThreadPoolExecutor(1,?1,
          ????????????????????????????0L,?TimeUnit.MILLISECONDS,
          ????????????????????????????new?LinkedBlockingQueue()));
          }

          ThreadPoolExecutor?類

          七大參數(shù)

          ThreadPoolExecutor類主要有以下七個參數(shù):

          • int corePoolSize: 核心線程池大小

          • int maximumPoolSize: 最大核心線程池大小

          • long keepAliveTime: 線程空閑后的存活時間

          • TimeUnit unit: 超時單位

          • BlockingQueue workQueue: 阻塞隊列

          • ThreadFactory threadFactory: 線程工廠:創(chuàng)建線程的,一般默認

          • RejectedExecutionHandler handle: 拒絕策略

          四種拒絕策略

          拒絕策略就是當隊列滿時,線程如何去處理新來的任務。

          Java內置了四種拒絕策略:

          • ThreadPoolExecutor.CallerRunsPolicy()

          • ThreadPoolExecutor.AbortPolicy()

          • ThreadPoolExecutor.DiscardPolicy()

          • ThreadPoolExecutor.DiscardOldestPolicy()

          CallerRunsPolicy(調用者運行策略)

          功能:只要線程池沒有關閉,就由提交任務的當前線程處理。

          使用場景:一般在不允許失敗、對性能要求不高、并發(fā)量較小的場景下使用。

          AbortPolicy(中止策略)

          功能:當觸發(fā)拒絕策略時,直接拋出拒絕執(zhí)行的異常

          使用場景:ThreadPoolExecutor中默認的策略就是AbortPolicy,由于ExecutorService接口的系列ThreadPoolExecutor都沒有顯示的設置拒絕策略,所以默認的都是這個。

          DiscardPolicy(丟棄策略)

          功能:直接丟棄這個任務,不觸發(fā)任何動作

          使用場景:提交的任務無關緊要,一般用的少。

          DiscardOldestPolicy(棄老策略)

          功能:彈出隊列頭部的元素,然后嘗試執(zhí)行,相當于排隊的時候把第一個人打死,然后自己代替

          使用場景:發(fā)布消息、修改消息類似場景。當老消息還未執(zhí)行,此時新的消息又來了,這時未執(zhí)行的消息的版本比現(xiàn)在提交的消息版本要低就可以被丟棄了。

          線程池中的狀態(tài)

          • RUNNING?自然是運行狀態(tài),指可以接受任務執(zhí)行隊列里的任務

          • SHUTDOWN?指調用了?shutdown()?方法,不再接受新任務了,但是隊列里的任務得執(zhí)行完畢。

          • STOP?指調用了?shutdownNow()?方法,不再接受新任務,同時拋棄阻塞隊列里的所有任務并中斷所有正在執(zhí)行任務。

          • TIDYING?所有任務都執(zhí)行完畢,在調用?shutdown()/shutdownNow()?中都會嘗試更新為這個狀態(tài)。

          • TERMINATED?終止狀態(tài),當執(zhí)行?terminated()?后會更新為這個狀態(tài)。

          處理流程

          提交一個任務到線程池中,線程池的處理流程如下:

          • 判斷線程池里的核心線程是否都在執(zhí)行任務

            • 是:進入下個流程。

            • 否:調用/創(chuàng)建一個新的核心線程來執(zhí)行任務。

          • 線程池判斷工作隊列是否已滿

            • 是:進入下個流程。

            • 否:將新提交的任務存儲在這個工作隊列里。

          • 判斷線程池里的所有線程是否都處于工作狀態(tài)

            • 是:交給拒絕策略來處理這個任務。

            • 否:調用/創(chuàng)建一個新的工作線程來執(zhí)行任務。

          具體使用

          創(chuàng)建

          不過最好不要使用Executors來創(chuàng)建線程,原因如下(參考自——阿里巴巴Java開發(fā)手冊):

          • FixedThreadPool?和?SingleThreadPool:允許的請求隊列長度為 Integer.MAX_VALUE,可能會堆積大量的請求,從而導致 OOM

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

          推薦使用ThreadPoolExecutor類自行創(chuàng)建

          //?自定義線程池
          ExecutorService?threadPool?=?new?ThreadPoolExecutor(
          ??2,
          ??Runtime.getRuntime().availableProcessors(),//CPU的核心數(shù),適合CPU密集型任務
          ??3,
          ??TimeUnit.SECONDS,
          ??new?LinkedBlockingDeque<>(3),
          ??Executors.defaultThreadFactory(),
          ??new?ThreadPoolExecutor.DiscardOldestPolicy());

          合理配置線程

          線程池不是越大越好,要根據(jù)任務類型合理進行配置

          • IO 密集型任務:盡可能的多配置線程

          • CPU 密集型任務:(大量復雜的運算)應當分配較少的線程

          執(zhí)行

          有兩個方法可以執(zhí)行任務executesubmit

          • execute提交沒有返回值,不能判斷是否執(zhí)行成功。

          • submit會返回一個Future對象,通過Futureget()方法來獲取返回值。

          區(qū)別:

          • 接收的參數(shù)不一樣

            • execute提交的方式只能提交一個Runnable的對象

            • submit有三種

          • submit有返回值,而execute沒有

          • submit方便Exception處理

          • executeExecutor接口中唯一定義的方法

          • submitExecutorService(該接口繼承Executor)中定義的方法

          關閉

          線程池使用完畢,需要對其進行關閉,有兩種方法

          • shutdown():不再繼續(xù)接收新的任務,執(zhí)行完成已有任務后關閉

          • shutdownNow():直接關閉,若果有任務嘗試停止




          關注武哥聊編程

          每天進步一點點



          點贊是最大的支持?

          瀏覽 48
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  黄色一级免费看 | 天天日天天添天天爽 | 欧美操逼国产日韩 | 中文字幕成人乱码熟女 | 免费视频在线观看一区 |