国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Tomcat如何修正JDK原生線程池Bug?

Tomcat如何修正JDK原生線程池Bug?

2021-08-20 23:22JavaEdge Java教程

為提高處理能力和并發度,Web容器一般會把處理請求的任務放到線程池,而JDK的原生線程池先天適合CPU密集型任務,并不適合我們通常的 I/O 密集任務處理,于是Tomcat改造之。

Tomcat如何修正JDK原生線程池Bug?

為提高處理能力和并發度,Web容器一般會把處理請求的任務放到線程池,而JDK的原生線程池先天適合CPU密集型任務,并不適合我們通常的 I/O 密集任務處理,于是Tomcat改造之。

Tomcat 線程池原理

其實ThreadPoolExecutor的參數主要有如下關鍵點:

  • 限制線程個數 

Tomcat如何修正JDK原生線程池Bug?

  • 限制隊列長度

Tomcat如何修正JDK原生線程池Bug?

而Tomcat對這倆資源都需要限制,否則高并發下CPU、內存都有被耗盡可能。因此Tomcat的線程池傳參:

  1. // 定制的任務隊列 
  2. taskqueue = new TaskQueue(maxQueueSize); 
  3.  
  4. // 定制的線程工廠 
  5. TaskThreadFactory tf = new TaskThreadFactory(namePrefix, 
  6.                                daemon, 
  7.                                getThreadPriority() 
  8. ); 
  9.  
  10. // 定制線程池 
  11. executor = new ThreadPoolExecutor(getMinSpareThreads(), 
  12.                   getMaxThreads(), 
  13.                      maxIdleTime,  
  14.                      TimeUnit.MILLISECONDS, 
  15.                      taskqueue, 
  16.                      tf); 

Tomcat對線程數也有限制,設置:

  • 核心線程數(minSpareThreads)
  • 最大線程池數(maxThreads)

Tomcat線程池還有自己的特色任務處理流程,通過重寫execute方法實現了自己的特色任務處理邏輯:

  1. 前corePoolSize個任務時,來一個任務就創建一個新線程
  2. 再有任務,就把任務放入任務隊列,讓所有線程去搶。若隊列滿,就創建臨時線程
  3. 總線程數達到maximumPoolSize,則繼續嘗試把任務放入任務隊列
  4. 若緩沖隊列也滿了,插入失敗,執行拒絕策略

和 JDK 線程池的區別就在step3,Tomcat在線程總數達到最大數時,不是立即執行拒絕策略,而是再嘗試向任務隊列添加任務,添加失敗后再執行拒絕策略。

具體又是如何實現的呢?

Tomcat如何修正JDK原生線程池Bug?

  1. public void execute(Runnable command, long timeout, TimeUnit unit) { 
  2.     submittedCount.incrementAndGet(); 
  3.     try { 
  4.         // 調用JDK原生線程池的execute執行任務 
  5.         super.execute(command); 
  6.     } catch (RejectedExecutionException rx) { 
  7.        // 總線程數達到maximumPoolSize后,JDK原生線程池會執行默認拒絕策略 
  8.         if (super.getQueue() instanceof TaskQueue) { 
  9.             final TaskQueue queue = (TaskQueue)super.getQueue(); 
  10.             try { 
  11.                 // 繼續嘗試把任務放入任務隊列 
  12.                 if (!queue.force(command, timeout, unit)) { 
  13.                     submittedCount.decrementAndGet(); 
  14.                     // 若緩沖隊列還是滿了,插入失敗,執行拒絕策略。 
  15.                     throw new RejectedExecutionException("..."); 
  16.                 } 
  17.             }  
  18.         } 
  19.     } 

定制任務隊列

Tomcat線程池的execute方法第一行:

  1. submittedCount.incrementAndGet(); 

任務執行失敗,拋異常時,將該計數器減一:

  1. submittedCount.decrementAndGet(); 

Tomcat線程池使用 submittedCount 變量維護已提交到線程池,但未執行完的任務數量。

為何要維護這樣一個變量呢?

Tomcat的任務隊列TaskQueue擴展了JDK的LinkedBlockingQueue,Tomcat給了它一個capacity,傳給父類LinkedBlockingQueue的構造器。

  1. public class TaskQueue extends LinkedBlockingQueue<Runnable> { 
  2.  
  3.   public TaskQueue(int capacity) { 
  4.       super(capacity); 
  5.   } 
  6.   ... 

capacity參數通過Tomcat的 maxQueueSize 參數設置,但maxQueueSize默認值為Integer.MAX_VALUE:這樣,當前線程數達到核心線程數后,再來的任務,線程池會把任務添加到任務隊列,并且總會成功,就永遠無機會創建新線程了。

為此,TaskQueue重寫了LinkedBlockingQueue#offer,在合適時機返回false,表示任務添加失敗,線程池此時會創建新的線程。

什么叫合適時機?

  1. public class TaskQueue extends LinkedBlockingQueue<Runnable> { 
  2.  
  3.   ... 
  4.    @Override 
  5.   // 線程池調用任務隊列的方法時,當前線程數 > core線程數 
  6.   public boolean offer(Runnable o) { 
  7.  
  8.       // 若線程數已達max,則不能創建新線程,只能放入任務隊列 
  9.       if (parent.getPoolSize() == parent.getMaximumPoolSize())  
  10.           return super.offer(o); 
  11.            
  12.       // 至此,表明 max線程數 > 當前線程數 > core線程數 
  13.       // 說明可創建新線程: 
  14.        
  15.       // 1. 若已提交任務數 < 當前線程數 
  16.       //    表明還有空閑線程,無需創建新線程 
  17.       if (parent.getSubmittedCount()<=(parent.getPoolSize()))  
  18.           return super.offer(o); 
  19.            
  20.       // 2. 若已提交任務數 > 當前線程數 
  21.       //    線程不夠用了,返回false去創建新線程 
  22.       if (parent.getPoolSize()<parent.getMaximumPoolSize())  
  23.           return false
  24.            
  25.       // 默認情況下總是把任務放入任務隊列 
  26.       return super.offer(o); 
  27.   } 
  28.    

所以Tomcat維護 已提交任務數 是為了在任務隊列長度無限時,讓線程池還能有機會創建新線程。

原文鏈接:https://mp.weixin.qq.com/s/7MOOhnI5qsoi8uAihLXy7A

延伸 · 閱讀

精彩推薦
  • Java教程淺談java 中equals和==的區別

    淺談java 中equals和==的區別

    這篇文章主要介紹了java 中equals和==的區別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小...

    獨特潤許多人5982021-07-21
  • Java教程mybatis批量新增、刪除、查詢和修改方式

    mybatis批量新增、刪除、查詢和修改方式

    這篇文章主要介紹了mybatis批量新增、刪除、查詢和修改方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教...

    xuforeverlove7492022-01-24
  • Java教程Java開發常見異常及解決辦法詳解

    Java開發常見異常及解決辦法詳解

    這篇文章主要介紹了java程序常見異常及處理匯總,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考...

    cutercorley12252021-12-18
  • Java教程Spring Cloud Gateway 如何修改HTTP響應信息

    Spring Cloud Gateway 如何修改HTTP響應信息

    這篇文章主要介紹了Spring Cloud Gateway 修改HTTP響應信息的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教...

    帷幄庸者13712021-10-13
  • Java教程Spring 6.0 將停止支持 Freemarker 和 JSP

    Spring 6.0 將停止支持 Freemarker 和 JSP

    Spring Framework 6.0 第一個里程碑版本已經發布,目前已經可以從Spring Repo獲取。這里有一些新變更我們可以提前了解一下。...

    碼農小胖哥12642021-12-31
  • Java教程淺談sql_@SelectProvider及使用注意說明

    淺談sql_@SelectProvider及使用注意說明

    這篇文章主要介紹了sql_@SelectProvider及使用注意說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教...

    icecoola_6892021-11-04
  • Java教程二進制中1的個數

    二進制中1的個數

    這篇文章介紹了二進制中1的個數,有需要的朋友可以參考一下 ...

    java之家2662019-10-15
  • Java教程mybatis調用存儲過程的實例代碼

    mybatis調用存儲過程的實例代碼

    這篇文章主要介紹了mybatis調用存儲過程的實例,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    動力節點11732021-01-25
主站蜘蛛池模板: 在线激情视频 | 国产精品一区三区 | 国产成人综合一区二区三区 | 中文字幕在线看 | 男女全黄一级一级高潮免费看 | 亚洲怡红院在线观看 | 欧美一级二级三级 | 国产成人精品一区二区三区网站观看 | 亚洲精品久久久久久一区二区 | www免费在线观看 | 欧美一级免费 | 欧美日本免费一区二区三区 | 欧美成人一区二区三区 | 日韩精品av一区二区三区 | 国产一区二区久久 | 亚洲三区在线观看 | 日韩有码在线播放 | 成人免费激情视频 | 欧美狠狠操| 欧美日韩一区二区三区在线观看 | 国产伊人av | 99精品视频在线 | 久久久精品一区二区 | 成年人在线看片 | 日本免费中文字幕 | 在线播放亚洲 | 久久久91精品国产一区二区三区 | 国产一级视频在线观看 | 天天操网| 国产激情偷乱视频一区二区三区 | |级毛片 | 午夜资源| 日韩一二三区视频 | 亚洲一区二区三区在线免费观看 | 欧美日韩不卡 | 国产一区二区三区在线观看免费 | 欧美一区二区三区精品 | 人人射在线观看 | 国产成人影院 | 黄色毛片免费看 | 精品国产乱码久久久久久牛牛 |