ThreadPoolExecutor配置使用詳解附結果說明

線程池ThreadPoolExcutor的使用

摘自阿里巴巴開發手冊:

【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣 的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。 說明:Executors 返回的線程池對象的弊端如下: 1FixedThreadPool SingleThreadPool: 允許的請求隊列長度爲 Integer.MAX_VALUE,可能會堆積大量的請求,從而導致 OOM 2CachedThreadPool 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中的幾個靜態屬性:NANOSECONDSMICROSECONDSMILLISECONDSSECONDS 
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;

                }

     }

}

 

執行結果分析:

put :work@ 1           |線程數未達到核心線程數目,新開線程執行work1

start------work@ 1      |work1執行

put :work@ 2           |線程數未達到核心線程數目,新開線程執行work2

start------work@ 2      |work2執行

put :work@ 3           |核心線程數滿,隊列未滿,將work3添加入隊列

put :work@ 4           |核心線程數滿,隊列未滿,將work4添加入隊列

put :work@ 5           |核心線程數滿,隊列未滿,將work5添加入隊列

put :work@ 6           |核心線程數滿,隊列已滿,新開線程執行work6

start------work@ 6      |work6執行

put :work@ 7           |核心線程數滿,隊列已滿,新開線程執行work7

start------work@ 7      |work7執行

put :work@ 8           |最大線程數滿,隊列已滿,按照DiscardOldestHandler丟棄work3,將work8加入隊列

put :work@ 9           |最大線程數滿,隊列已滿,按照DiscardOldestHandler丟棄work4,將work9加入隊列

put :work@ 10          |最大線程數滿,隊列已滿,按照DiscardOldestHandler丟棄work5,將work10加入隊列

put :work@ 11          |

put :work@ 12          |

put :work@ 13          |

put :work@ 14          |

put :work@ 15          |

put :work@ 16          |

put :work@ 17          |

put :work@ 18          |最大線程數滿,隊列已滿,按照DiscardOldestHandler丟棄work15,將work18加入隊列

put :work@ 19          |最大線程數滿,隊列已滿,按照DiscardOldestHandler丟棄work16,將work19加入隊列

put :work@ 20          |最大線程數滿,隊列已滿,按照DiscardOldestHandler丟棄work17,將work20加入隊列

start------work@ 18     |work18開始執行

start------work@ 19     |work19開始執行

start------work@ 20     |work20開始執行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章