線程池ThreadPoolExcutor的使用


 

摘自阿里巴巴開發手冊:

      【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣 的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。 說明:Executors 返回的線程池對象的弊端如下: 1)FixedThreadPool 和 SingleThreadPool: 允許的請求隊列長度為 Integer.MAX_VALUE,可能會堆積大量的請求,從而導致 OOM。 2)CachedThreadPool 和 ScheduledThreadPool: 允許的創建線程數量為 Integer.MAX_VALUE,可能會創建大量的線程,從而導致 OOM。

 

摘自網絡:

1.優勢: 
(1)降低資源消耗。通過重復利用已創建的線程降低線程創建、銷毀線程造成的消耗。 
(2)提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。 
(3)提高線程的可管理性。線程是稀缺資源,如果入限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配、調優和監控。

2.線程池的創建 
new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler) 
(1)corePoolSize: 線程池維護線程的最少數量 (core : 核心) 
(2)maximumPoolSize: 線程池維護線程的最大數量 
(3)keepAliveTime: 線程池維護線程所允許的空閑時間 
(4)unit: 線程池維護線程所允許的空閑時間的單位 
(5)workQueue: 線程池所使用的緩沖隊列 
(6)handler: 線程池對拒絕任務的處理策略

3.添加任務到線程池 
通過 execute(Runnable)方法被添加到線程池,任務就是一個 Runnable類型的對象,任務的執行方法就是 Runnable類型對象的run()方法。 
當一個任務通過execute(Runnable)方法欲添加到線程池時: 
如果此時線程池中的數量小於corePoolSize,即使線程池中的線程都處於空閑狀態,也要創建新的線程來處理被添加的任務。 
如果此時線程池中的數量等於 corePoolSize,但是緩沖隊列 workQueue未滿,那么任務被放入緩沖隊列。 
如果此時線程池中的數量大於corePoolSize,緩沖隊列workQueue滿,並且線程池中的數量小於maximumPoolSize,建新的線程來處理被添加的任務。 
如果此時線程池中的數量大於corePoolSize,緩沖隊列workQueue滿,並且線程池中的數量等於maximumPoolSize,那么通過 handler所指定的策略來處理此任務。 
也就是:處理任務的優先級為: 
核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。 
當線程池中的線程數量大於 corePoolSize時,如果某線程空閑時間超過keepAliveTime,線程將被終止。這樣,線程池可以動態的調整池中的線程數。 
unit可選的參數為java.util.concurrent.TimeUnit中的幾個靜態屬性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。 
workQueue常用的是:java.util.concurrent.ArrayBlockingQueue 
handler有四個選擇: 
ThreadPoolExecutor.AbortPolicy(): 拋出java.util.concurrent.RejectedExecutionException異常 
ThreadPoolExecutor.CallerRunsPolicy(): 重試添加當前的任務,他會自動重復調用execute()方法 
ThreadPoolExecutor.DiscardOldestPolicy(): 拋棄舊的任務 
ThreadPoolExecutor.DiscardPolicy(): 拋棄當前的任務

4.線程池的使用場合 
(1)單個任務處理的時間比較短; 
(2)需要處理的任務數量大;

6、線程池的應用舉例:

package hh;
import java.io.Serializable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExcutorDemo {
     private static int produceTaskSleepTime = 5;
     private static int consumeTaskSleepTime = 5000;
     private static int produceTaskMaxNumber = 20; //定義最大添加10個線程到線程池中
     public static void main(String[] args) {
            //構造一個線程池
           ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3,
                     TimeUnit. SECONDS, new ArrayBlockingQueue<Runnable>(3),
                      new ThreadPoolExecutor.DiscardOldestPolicy());
            for( int i=1; i<= produceTaskMaxNumber;i++){
                 try {
                      //一個任務,並將其加入到線程池
                     String work= "work@ " + i;
                     System. out.println( "put :" +work);
                      threadPool.execute( new ThreadPoolTask(work));
                      //便於觀察,等待一段時間
                     Thread. sleep(produceTaskSleepTime);
                } catch (Exception e) {
                      e.printStackTrace();
                     }
                }
     }

     /**
     * 線程池執行的任務
     * @author zhu
     */
     public static class ThreadPoolTask implements Runnable,Serializable{
            private static final long serialVersionUID = 0;
            //保存任務所需要的數據
            private Object threadPoolTaskData;
           ThreadPoolTask(Object works){
                 this. threadPoolTaskData =works;
           }
            public void run(){
                 //處理一個任務,這里的處理方式太簡單了,僅僅是一個打印語句
                System. out.println( "start------"+threadPoolTaskData );
                 try {
                      //便於觀察,等待一段時間
                     Thread. sleep(consumeTaskSleepTime);
                     } catch (Exception e) {
                            e.printStackTrace();
                           }
                 threadPoolTaskData = null;
                }
            public Object getTask(){
                 return this. threadPoolTaskData;
                }
     }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM