Java線程池ThreadPoolExecutor

  • 建立對象僅僅在JVM的堆裏爲線程分配一塊內存,而建立一個線程須要調用操做系統內核的API,而後操做系統要爲線程分配一系列的資源。因此線程是一個重量級的對象,應該避免頻繁的建立和銷燬。
  • 線程池是一種生產者-消費者模式

ThreadPoolExecutor

ThreadPoolExecutor的構造函數比較複雜,最完備的構造有7個參數。html

ThreadPoolExecutor(    
    //(線程數量)線程池最小線程數。
    int    corePoolSize,    
    //線程池建立的最大線程數。
    int    maximumPoolSize,        
   
    //當線程池中空閒線程數量超過corePoolSize時,多餘的線程會在多長時間內被銷燬。
    long    keepAliveTime,
    //keepAliveTime的單位。
    TimeUnit    unit,
     /**
     * 任務隊列,
     * 被添加到線程池中,但還沒有被執行的任務;
     * 它通常分爲直接提交隊列、有界任務隊列、無界任務隊列、優先任務隊列幾種;
     */
    BlockingQueue<Runnable>    workQueue,
    /**
     *線程工廠,用於建立線程,通常用默認便可。
     */
    ThreadFactory    threadFactory,    
    //自定義拒絕策略。當任務太多時如何拒絕任務。
    RejectedExecutionHandler    handler
    )

參數說明補充:java

handler:經過這個參數你能夠自定義任務的拒絕策略。若是線程池中全部的線程都在忙碌,而且工做隊列也滿了(前提是工做隊列是有界隊列),那麼此時提交任務,線程池就會拒絕接收。至於拒絕的策略, 你能夠經過handler這個參數來指定。ThreadPoolExecutor已經提供瞭如下4種策略。緩存

  • CallerRunsPolicy:提交任務的線程本身去執行該任務。
  • AbortPolicy:默認的拒絕策略,會throws RejectedExecutionException
  • DiscardPolicy:直接丟棄任務,沒有任何異常拋出。
  • DiscardOldestPolicy:丟棄最老的任務,其實就是把最先進入工做隊列的任務丟棄,而後把新任務加入 到工做隊列。

詳情:https://www.cnblogs.com/dafan...併發

ThreadPoolExecutor提供的3個submit()方法和1個FutureTask工具類來支持得到執行任務執行結果的需求:函數

//    提交Runnable任務 
Future<?> submit(Runnable task); 
//    提交Callable任務 
Future<T> submit(Callable<T> task); 
//    提交Runnable任務及結果引⽤        
Future<T> submit(Runnable task,    T result);
  1. 提交Runnable任務submit(Runnable task) :這個方法的參數是一個Runnable接口,Runnable接扣的run()方法是沒有返回值的,因此 submit(Runnable task) 這個方法返回的Future僅能夠用來斷言任務已經結束了,相似於Thread.join()。
  2. 提交Callable任務 submit(Callable<T> task):這個方法的參數是一個Callable接口,它只有一個 call()方法,而且這個方法是有返回值的,因此這個方法返回的Future對象能夠經過調用其get()方法來獲取任務的執行結果。
  3. 提交Runnable任務及結果引用 submit(Runnable task, T result):這個方法頗有意思,假設這個方法返回的Future對象是f,f.get()的返回值就是傳給submit()方法的參數result。Runnable接口的實現類Task聲明瞭一個有 參構造函數 Task(Result r) ,建立Task對象的時候傳入了result對象,這樣就能在類Task的run()方法 中對result進行各類操做了。result至關於主線程和子線程之間的橋樑,經過它主子線程能夠共享數據。

使用併發工具包Executors建立線程池(不建議使用)工具

//建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。
ExecutorService executor1 = Executors.newCachedThreadPool();

//建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
ExecutorService executor2 = Executors.newFixedThreadPool(10);

//建立一個定長線程池,支持定時及週期性任務執行。
ExecutorService executor3 = Executors.newScheduledThreadPool (10);

//建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行。
ExecutorService executor4 = Executors.newSingleThreadExecutor ();

不建議使用Executors,Executors提供的不少方法默認使用都是無界的LinkedBlockingQueue, 高負載情境下,無界隊列很容易致使OOM,而OOM會致使全部請求都沒法處理,因此強力建議使用有界隊列。操作系統

使用線程池要注意什麼

無界隊列很容易致使OOM,而OOM會致使全部請求都沒法處理,因此強力建議使用有界隊列。線程

使用有界隊列,當任務過多時,線程池會觸發執行拒絕策略,線程默認的拒絕會。code


碼字不易若是對你有幫助請給個關注htm

愛技術愛生活 QQ羣: 894109590

相關文章
相關標籤/搜索