ThreadPoolExecutor 最基礎的線程池

在Java中,線程池的概念是Executor這個接口,具體實現爲ThreadPoolExecutor類,學習Java中的線程池,就能夠直接學習他了,對線程池的配置,就是對ThreadPoolExecutor構造函數的參數的配置。java

//五個參數的構造函數
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)
 
//六個參數的構造函數-1
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory)
 
//六個參數的構造函數-2
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler)
 
//七個參數的構造函數
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
  • int corePoolSize => 該線程池中核心線程數最大值
線程池新建線程的時候,若是當前線程總數小於corePoolSize,則新建的是核心線程,若是超過corePoolSize,則新建的是非核心線程

核心線程默認狀況下會一直存活在線程池中,即便這個核心線程啥也不幹(閒置狀態)。

若是指定ThreadPoolExecutor的allowCoreThreadTimeOut這個屬性爲true,那麼核心線程若是不幹活(閒置狀態)的話,超過必定時間(時長下面參數決定),就會被銷燬掉

很好理解吧,正常狀況下你不幹活我也養你,由於我總有用到你的時候,但有時候特殊狀況(好比我本身都養不起了),那你不幹活我就要把你幹掉了
  • int maximumPoolSize 該線程池中線程總數最大值函數

  • long keepAliveTime TimeUnit unit 該線程池中非核心線程閒置超時時長,一個非核心線程,若是不幹活(閒置狀態)的時長超過這個參數所設定的時長,就會被銷燬掉學習

  • BlockingQueue<Runnable> workQueue 見 這裏.net

  • ThreadFactory threadFactory 當須要建立一個新的線程時,會調用該方法。線程

  • RejectedExecutionHandler handler 這裏想對拒絕策略,在使用線程池而且使用有界隊列的時候,若是隊列滿了,任務添加到線程池的時候就會有問題,針對這些問題java線程池提供瞭如下幾種策略:code

    1. AbortPolicy 該策略是線程池的默認策略。使用該策略時,若是線程池隊列滿了丟掉這個任務而且拋出RejectedExecutionException異常。
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             //不作任何處理,直接拋出異常
             throw new RejectedExecutionException("Task " + r.toString() +
                                                  " rejected from " +
                                                  e.toString());
         }
    1. DiscardPolicy 這個策略和AbortPolicy的slient版本,若是線程池隊列滿了,會直接丟掉這個任務而且不會有任何異常。
    2. DiscardOldestPolicy 丟棄最老的。也就是說若是隊列滿了,會將最先進入隊列的任務刪掉騰出空間,再嘗試加入隊列。
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             if (!e.isShutdown()) {
             	//移除隊頭元素
                 e.getQueue().poll();
                 //再嘗試入隊
                 e.execute(r);
             }
         }
    1. CallerRunsPolicy若是添加到線程池失敗,那麼主線程會本身去執行該任務,不會等待線程池中的線程去執行。
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             if (!e.isShutdown()) {
                 //直接執行run方法
                 r.run();
             }
         }
    1. 自定義

PS: 不少文章裏並不關注拒絕策略,可是實際上,在開發過程當中咱們須要想象,若是線程被拒絕咱們應該怎麼處理。blog

java線程池類

線程池最基礎的類是Executor 是一個接口,只定義了一個execute,方法,表示運行一個Runnable。繼承

public interface Executor {
    void execute(Runnable command);
}

而後是 ExecutorService 它也是一個接口,繼承了 Executor,在此基礎上主要提供了shutdown和submit能力。shutdown用於控制線程池中止,submit相似於execute,可是提供了Future支持(帶返回值)。接口

而後就是虛類 AbstractExecutorService 繼承了 ExecutorService 實現一些默認方法。隊列

再上層就是ThreadPoolExecutor 實現了 AbstractExecutorService。

常見線程池

Executors類中提供了一些默認特性的線程池,再加上自定義 ThreadPoolExecutor 基本上就夠用了。

  • FixedThreadPool 定長線程池,超出的線程會在隊列中等待(maximumPoolSize值至關於無效)
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • CachedThreadPool 很是任性的線程池,有空閒用空閒沒空閒直接起線程,不會等待。maximumPoolSize 是 Integer.MAX_VALUE,因此通常不會出現線程滿的狀況。不過會出現資源不夠建立不了線程報錯,慎用。
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • SingleThreadPool 只有一個線程能執行,其餘後入的線程排隊。
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • ScheduledThreadPool 見下

ScheduledThreadPool

繼承自 ThreadPoolExecutor,增長了定時功能。若是想實現定時運行就考慮一下這個東西。

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

使用的DelayedWorkQueue 隊列內元素必須實現Delayed接口,這就意味着你傳進去的任務必須先實現Delayed接口。這個隊列接收到任務時,首先先入隊,只有達到了指定的延時時間,纔會執行任務

參考

https://blog.csdn.net/jgteng/article/details/54411423 https://blog.csdn.net/z69183787/article/details/80520659

相關文章
相關標籤/搜索