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

          多線程之線程池(上)

          共 2842字,需瀏覽 6分鐘

           ·

          2021-07-17 17:54


          前言

          最近一段時(shí)間,我們一直都在分享多線程相關(guān)知識(shí),也一直有用線程池,但是一直沒有介紹線程池相關(guān)知識(shí),所以今天我們就先來看下線程池相關(guān)的知識(shí)點(diǎn)。

          線程池

          ThreadPool,線程池,顧名思義就是存放線程的池子,也是jdk1.5引入的。對(duì)我們而言,它的最主要優(yōu)勢就是簡化了線程啟動(dòng)流程,讓我們可以更方便地使用多線程,再也不用手動(dòng)start線程,直接通過線程池提交我們的任務(wù)即可,而且合理使用線程池至于可以帶來以下幾個(gè)好處:

          • 降低資源消耗:復(fù)用線程,降低創(chuàng)建和銷毀線程帶來的資源消耗

          • 提高響應(yīng)速度:使用線程池,省去了線程創(chuàng)建和初始化過程,所以任務(wù)可以更快執(zhí)行

          • 提高線程的可管理性:可以直接通過線程池管理、監(jiān)控、調(diào)度線程,線程管理更方便

          常用線程池

          常用的線程池有SingleThreadExecutorCachedThreadPoolScheduledThreadPoolFixedThreadPool,他們分別是單線程調(diào)度器,緩存線程池,定時(shí)任務(wù)線程池和固定線程池,他們都可以通過Executors創(chuàng)建,調(diào)用對(duì)應(yīng)的靜態(tài)方法即可,由于這一塊的內(nèi)容比較多,所以今天就簡單提一下,后面專門講一次。

          自定義線程池

          我們今天著重講下自定義線程池,自定義線程池也很簡單,直接new ThreadPoolExecutor(),然后傳入對(duì)應(yīng)的參數(shù)即可,大家可以看下下面的示例:

          int corePoolSize = 10;
          int maximumPoolSize = 20;
          long keepAliveTime = 1000;
          TimeUnit unit = TimeUnit.MICROSECONDS;
          BlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
          ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
          for (int i = 0; i < 50; i++) {
              threadPoolExecutor.execute(() -> {
                  String name = Thread.currentThread().getName();
                  System.out.println("hello threadPool: "+ name);
              });
          }
          threadPoolExecutor.shutdown();

          ThreadPoolExecutor有三個(gè)構(gòu)造方法,至少需要三個(gè)參數(shù)

          其中第一個(gè)參數(shù)是線程池的基本大小,當(dāng)你提交一個(gè)任務(wù)到線程池時(shí),線程池會(huì)創(chuàng)建一個(gè)線程來執(zhí)行任務(wù),即使有空閑的線程存在,線程池依然會(huì)啟動(dòng)一個(gè)新線程來執(zhí)行當(dāng)前任務(wù),直到線程池中的線程數(shù)達(dá)到線程基本大小(corePoolSize);

          第二個(gè)參數(shù)是線程池允許創(chuàng)建的最大線程數(shù)。如果工作隊(duì)列(第三個(gè)參數(shù))滿了,且創(chuàng)建線程數(shù)已達(dá)到線程池基本大小,則線程池會(huì)繼續(xù)創(chuàng)建新的線程來執(zhí)行任務(wù)。如果你指定的工作隊(duì)列是無界的,那這個(gè)參數(shù)也就失效了。

          第三個(gè)參數(shù)就是線程池工作隊(duì)列,就是當(dāng)你需要執(zhí)行的任務(wù)超過線程池基本大小的時(shí)候,會(huì)把超出部分放進(jìn)工作隊(duì)列,等待線程池基本線程資源釋放。

          下面我們分別驗(yàn)證以上三點(diǎn),運(yùn)行上面的示例代碼:

          在第一次循環(huán)的時(shí)候(i=0),我們發(fā)現(xiàn)線程池的size0,活動(dòng)線程數(shù)也是0,任務(wù)隊(duì)列也是0,完成任務(wù)數(shù)也是0,這也說明線程池在最開始的時(shí)候是沒有創(chuàng)建線程的;

          然后我們讓他循環(huán)到第9次(i=8),這時(shí)候線程池已經(jīng)被初始化,有8個(gè)線程(由于斷點(diǎn)的原因,第9個(gè)線程尚未被創(chuàng)建),活動(dòng)線程數(shù)5,完成執(zhí)行的任務(wù)數(shù)3,任務(wù)隊(duì)列還是0,說明確實(shí)在未達(dá)到線程池基本大小時(shí),會(huì)不斷創(chuàng)建新的線程;

          我們繼續(xù)執(zhí)行,讓他循環(huán)到第15次(i=14),可結(jié)果似乎和我們預(yù)期不一樣,按照預(yù)期,線程池的size應(yīng)該是10,活動(dòng)線程數(shù)也是10,任務(wù)隊(duì)列也是4,完成任務(wù)數(shù)可能不確定,所以這里肯定不能通過debug的方式來看了,因?yàn)?code style="overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);">debug停頓之后好多線程資源已經(jīng)被釋放,任務(wù)根本就不會(huì)堆積,所以任務(wù)隊(duì)列就不會(huì)有數(shù)據(jù):

          所以這里我在線程池啟動(dòng)任務(wù)前加一行打印,打印線程池?cái)?shù)據(jù)

          然后在運(yùn)行,就可以拿到運(yùn)行數(shù)據(jù):

          這樣的數(shù)據(jù)才是真實(shí)的,因?yàn)閷?shí)際運(yùn)行的時(shí)候,線程啟動(dòng)是非常快的,所以執(zhí)行完成的任務(wù)數(shù)應(yīng)該是0,等待任務(wù)數(shù)是4

          我們前面設(shè)定的最大線程數(shù)是20,但是翻看運(yùn)行記錄,我發(fā)現(xiàn)線程池的大小始終是10,說明只要不打到任務(wù)隊(duì)列的上限,并不會(huì)創(chuàng)建新的線程,這里我們把循環(huán)次數(shù)改為60,然后運(yùn)行下:

          但是依然沒有創(chuàng)建新的線程,因?yàn)檫€是沒有達(dá)到任務(wù)隊(duì)列上限,我們把循環(huán)次數(shù)再調(diào)大一點(diǎn),調(diào)到70:

          現(xiàn)在線程池的大小就變成了19,活動(dòng)線程數(shù)19,但是這時(shí)候如果你繼續(xù)調(diào)大循環(huán)次數(shù),線程池就會(huì)報(bào)錯(cuò)了:

          這個(gè)錯(cuò)誤的原因就是線程池資源已經(jīng)耗盡了,無法再接收新的任務(wù)了,這也就是說線程池能夠處理的最大任務(wù)數(shù)是corePoolSize + maximumPoolSize + workQueue.size()  ,當(dāng)然,如果你的workQueue不設(shè)定大小,那永遠(yuǎn)都不會(huì)報(bào)這個(gè)錯(cuò)誤,當(dāng)然maximumPoolSize也就無效了。

          總結(jié)

          原本打算線程池一次分享完的,但是實(shí)際分享過程中發(fā)現(xiàn)內(nèi)容太多了(已經(jīng)一千五百字了),所以今天就先到這里,明天再繼續(xù)分享線程池其他內(nèi)容。總的來說,今天的內(nèi)容已經(jīng)說明白了線程池很多基礎(chǔ)的知識(shí)點(diǎn)(反正我自己覺得我都有好多收獲),算是干貨滿滿吧,你如果掌握了這些知識(shí)點(diǎn),至少在使用線程池的過程中會(huì)少踩好多坑。好了,今天就先說這么多吧!

          - END -


          瀏覽 44
          點(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>
                  精品无码一区三区四区五区 | 五月天婷婷大香蕉 | 翔田千里91 | 成人做爰A片免费看网站 | 一区二区三区四区在线看 |