使用線程池的目的是希望線程控制在某個范圍內,以免造成服務崩潰,所以在使用線程池的時候要多加注意。
記錄原因:一個webservice中轉項目,需求很簡單,提供webservice接口接收數據,然后入庫,再通過webservice將數據原樣推送給其他應用,推送數據給應用時使用的是線程池,保證一定的並發量處理代碼如下:
1 @Component 2 public class WebServiceClient { 3 private Logger logger = Logger.getLogger(this.getClass()); 4 private Configuration config = Configuration.getInstance(); 5 private ExecutorService executors = Executors.newFixedThreadPool(20); 6 7 @Autowired 8 private ZkMessagePushFailedService zkMessagePushFailedService; 9 /** 10 * webservice推送 11 * @param list 12 */ 13 public void webServicePush(List<byte[]> list){ 14 if (null != list && !list.isEmpty()){ 15 for (int i = 0; i < list.size(); i++) { 16 executors.execute(new Call((String) SerializeUtils.unserialize(list.get(i)))); 17 } 18 } 19 } 20 21 class Call implements Runnable{ 22 String content; 23 24 public Call(String content){ 25 this.content = content; 26 } 27 28 @Override 29 public void run() { 30 //省略業務代碼 31 32 logger.info("webservice exec end-------------------"); 33 } 34 } 35 }
在外部通過
1 WebServiceClient client = new WebServiceClient(); 2 client.webServicePush(list);
來調用webServicePush方法,乍一看沒什么問題,實際上問題很大。
項目上線幾天后,通過SSH就登錄不上服務器了(阿里雲服務器),但是頁面能訪問,只是沒有任何數據,通過阿里雲平台遠程登錄功能登錄后登錄不上,報以下錯誤:
--root:fork failed:Cannot allocate memory
剛開始還以為服務器被攻擊了,百度查了一下,說是線程數達到系統的最大線程數造成的,重啟阿里雲服務器,啟動tomcat和相關應用,通過linux命令ps -eLf | wc -l來查看進程及線程情況,發現tomcat進程下在不斷的增加線程,只增不減,最終導致以上問題。
通過一系列的排除法,發現就是線程池使用不當導致的,原因就在於我是用new的方式來創建對象的WebServiceClient client = new WebServiceClient(),而這個對象里有個線程池,就相當於每次創建一個對象的同時就創建了一個線程池,導致tomcat線程不斷的增加。
解決方法:
1、將線程池聲明為靜態的
private final static ExecutorService executors = Executors.newFixedThreadPool(20);
2、將WebServiceClient類做成單例的
自此該問題得到解決,粗心導致的,記錄一下。
————————————————
版權聲明:本文為CSDN博主「ganchunsaixx」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ganchunsaixx/java/article/details/100016408