限制Java線程池運行線程以及等待線程數量的策略

ChaHeim 8年前發布 | 30K 次閱讀 線程 線程池 Java 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<Runnable> 。我們需要做的第一個改造就是綁定有大小上線的BlockingQueue,在我的實現中綁定 ArrayBlockingQueue<Runnable> 并設置了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();
    }

  });
}</code></pre> 

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

 

來自: https://segmentfault.com/a/1190000005876711

 

 本文由用戶 ChaHeim 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!