1. 程式人生 > >限制Java執行緒池執行執行緒以及等待執行緒數量的策略

限制Java執行緒池執行執行緒以及等待執行緒數量的策略

對於 java.util.concurrent.Executors 所提供的 FixedThreadPool ,可以保證可以在記憶體中有固定數量的執行緒數執行。但是由於 FixedThreadPool 繫結的是 LinkedBlockingQueue 。佇列的上限沒有限制(預設上限為 Integer.MAX_VALUE ),不斷的提交新的執行緒,會造成任務在記憶體中長時間的堆積。

我們有可能面臨如下的場景,主執行緒不斷地提交任務執行緒,希望有固定數量的線上程中執行,也不想造成執行緒在記憶體中大量的等待堆積。由此需要我們自己定義一個執行緒池策略。 ThreadPoolExecutor 為我們執行緒池的設定提供了很大的靈活性。

首先看 FixedThreadPool 的實現:

 public static ExecutorService More ...newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
 return new ThreadPoolExecutor(nThreads, nThreads,
 0L, TimeUnit.MILLISECONDS,
 new LinkedBlockingQueue<Runnable>(),
 threadFactory);
 }

可以看到,FixedThreadPool繫結的是 LinkedBlockingQueue 。我們需要做的第一個改造就是繫結有大小上線的BlockingQueue,在我的實現中繫結 ArrayBlockingQueue 並設定了size。

第二個是採用CallerRunsPolicy。ThreadPoolExecutor可以定義不同的任務拒絕策略。CallerRunsPolicy指的是當執行緒池拒絕該任務的時候,執行緒在本地執行緒直接 execute 。這樣就限制了本地執行緒的迴圈提交流程。

 BlockingQueue<Runnable> workingQueue = new ArrayBlockingQueue<Runnable>(10);
 RejectedExecutionHandler rejectedExecutionHandler =
 new ThreadPoolExecutor.CallerRunsPolicy();
 ExecutorService threadPool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
 workingQueue, rejectedExecutionHandler);
 for (int i = 0; i < 100; i++) { 
 threadPool.submit(new Callable<Boolean>() {
 @Override
 public Boolean call() throws Exception {
 System.out.println("thread " + String.valueOf(threadNo) + " is called");
 Thread.sleep(10000);
 System.out.println("thread " + String.valueOf(threadNo) + " is awake");
 throw new Exception();
 }
 });
 }

程式碼中定義了大小為10的執行緒池,for迴圈提交了20個執行緒的時候,10個執行執行緒,10個執行緒放入了 workingQueue 。當提交到第21個執行緒的時候,會觸發RejectedExecutionHandler。在這裡我們配置了CallerRunsPolicy策略。所以會在主執行緒直接執行該執行緒。也就是說,在本程式中最多會有11個執行緒在執行,10個執行緒在等待。由此限制了執行緒池的等待執行緒數與執行執行緒數

如果你剛好是程式設計師,如果你剛好又是Java程式設計師,如果剛好你的技術又遇到了瓶頸但是你又拒絕平庸,期待蛻變,想進入一線網際網路公司或者給自己漲薪
我這裡剛好有一套自己儲存的Java進階學習資料。包含了Spring框架、Mybatis框架SpringBoot框架、SpringMVC框架、SpringCloud微服務、Dubbo框架、Redis快取、RabbitMq訊息、JVM調優、Tomcat容器、MySQL資料庫
兩千人群滿了 這個是 新群 Java高階進階群:963944895,免費傳送的喲