<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Loading

      【多線程】線程復用的原理

      在了解線程復用原理之前,我們再回顧一下之前在線程池的初始配置詳解的文章中提到的創建線程的流程
      image

      在線程提交線程任務的時候,線程池會提前判斷線程池中執行的任務是否達到核心線程數了,如果達到了核心線程數那么他就會將這個多出來的任務塞入隊列中,如果發現隊列中的任務數也達到了上限,這個時候線程池就會開始在核心線程數的基礎上創建更多的線程,當創建的線程達到了最大線程的線程數,并且線程隊列也滿了,這個時候就會觸發我們設置的拒絕策略。

      看到這里大家仔細思考一下,為什么線程池會設置一個核心線程數呢?這樣做的好處有啥,其實這里就是為了滿足線程復用的作用,在線程池中,我們提交給線程池的每個任務,在線程池中稱之為worker,在線程池初始化之后,線程池就會創建我們設置的核心線程數大小的線程數,當有任務進來的時候,線程池其實并不會去新創建線程來執行剛剛進來的任務,而是初始化創建的線程中直接獲取worker中的任務,執行他的run方法,當當前這個線程任務執行完成之后,就會再去無限循環的獲取worker列表中的下一個任務,依次循環,從而達到了線程復用的目的。

      知道了大概的流程,我們接下來再看看源碼。
      image.png

      第一段代碼

      if (command == null) 
          throw new NullPointerException();
      

      這段代碼對線程任務做了一個非空判斷,如果線程任務為null則會拋出空指針異常。

      第二段代碼

      if (workerCountOf(c) < corePoolSize) { 
          if (addWorker(command, true)) 
              return;
              c = ctl.get();
      }
      

      workerCountOf()方法為獲取當前正在運行的線程數,如果當前運行的線程數,小于核心線程數,這個時候就會添加一個線程任務到核心線程池中。
      可以看到addWorker(command, true)方法中傳入了一個true,這個布爾值代表我這次添加任務到線程池中需不需要創建額外的線程,ture就代表不需要創建額外的線程池,false就代表需要創建額外的線程。在當前這個情況,當前執行的任務的數量小于核心線程數,所以方法傳入的是ture。

      if (isRunning(c) && workQueue.offer(command)) { 
          int recheck = ctl.get();
          if (! isRunning(recheck) && remove(command)) 
              reject(command);
          else if (workerCountOf(recheck) == 0) 
              addWorker(null, false);
      }
      

      如果代碼執行到了這里,說明當前線程任務已經大于核心線程數了,那么這個時候就需要通過isRunning(c) && workQueue.offer(command)來檢查線程池狀態是否為Running,如果為Running就通過workQueue.offer(command)方法放入到隊列中,如果通過(! isRunning(recheck) && remove(command)) 判斷線程不在Running狀態,說明線程池就已經關閉掉了,這個時候就會執行remove(command)方法來移除剛剛添加到隊列任務中的任務,并通過reject(command)執行拒絕策略。
      如果發現線程在執行狀態下,這個時候就會通過workerCountOf(recheck) == 0來判斷之前的線程有沒有執行完成,如果之前的線程任務已經結束了這個時候workerCountOf(recheck)方法就會返回0,這個時候就代表這個任務可以加入線程池并通過addWorker(null, false)來創建一個新的線程

      else if (!addWorker(command, false)) 
          reject(command);
      

      執行到了這里,這個時候就代表著線程池已經停止工作了。或者任務隊列已經滿了,這個時候線程池不能再加入更多的線程,通過addWorker來創建新的線程時,如果創建新的線程不成功,這個時候會執行reject來執行拒絕策略。

      看到這里,可能大家還是會有點疑惑,這上面的代碼并沒有體現出線程復用的邏輯,其實玄機就在addWorker()這個方法,我們看下面的這張圖
      image.png
      在addWorker()方法中,里面的核心代碼其實是runWorker這個方法,其中入參的Worker就是我們提供給線程的任務隊列,runWorker獲取先獲取Worker中最先進來的任務,然后通過一個while方法去循環判斷,只要提供的線程任務不為null,那么她就會一直的循環執行。在這里,大家可能就會發現,我們提供給的多個線程任務,其實就是這一個while循環的線程中不斷的去執行,所以每個線程始終都在一個大的循環中,反復取任務執行任務,從而達到了線程復用的作用。

      總結

      其實為什么線程池需要使用的線程復用,其原因就是線程池的優點,節省了線程創建和關閉的開銷,以前我們普通執行線程,如果有1000個任務需要執行,這個時候就需要創建1000的線程,這個時候就會帶來1000的線程的創建和銷毀的開銷。如果我們使用了線程池,通過線程池線程復用的原理,我們1000的線程任務,肯能都會在5個線程了循環執行,這樣就節省了大量的線程創建銷毀的開銷,這就是使用線程復用的好處。

      posted @ 2022-01-29 15:20  鄧小白  閱讀(699)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 狠狠做五月深爱婷婷天天综合| 国产性色的免费视频网站| 亚洲精品国产自在久久| 国产亚洲精品aaaa片app| 日韩精品久久一区二区三| www国产无套内射com| 狠狠色噜噜狼狼狼色综合久| 日韩中文字幕有码av| 国产精品日韩av在线播放| 日本黄页网站免费观看| 国产69精品久久久久99尤物| 四虎成人精品永久网站| 免费国产精品黄色一区二区| 欧美色欧美亚洲高清在线观看| 国产免费网站看v片元遮挡| 九九热中文字幕在线视频| 四虎永久精品在线视频| 国产精品成人av电影不卡| 国产亚洲精久久久久久久91| 99在线精品国自产拍中文字幕| 精品国产一区二区三区香| 国产高跟黑色丝袜在线| 天天躁日日躁狠狠躁中文字幕| 女人被爽到高潮视频免费国产| 亚洲AVAV天堂AV在线网阿V| 麻豆一区二区三区蜜桃免费| 亚洲欧洲日韩精品在线| 熟女女同亚洲女同中文字幕 | 中文字幕乱码在线播放| 国产精品制服丝袜第一页| 五台县| 欧美牲交a欧美牲交aⅴ图片| 99riav精品免费视频观看| 中文字幕一区二区三区精彩视频| 日韩V欧美V中文在线| 丰满少妇高潮无套内谢| 日本不卡的一区二区三区| 亚洲欧美偷国产日韩| 麻豆成人精品国产免费| 91老熟女老人国产老太| 国产欧美日韩综合精品二区|