有界、無界隊列對ThreadPoolExcutor執行的影響


本文轉載自https://blog.csdn.net/kusedexingfu/article/details/72491864

 

Java提供了4鍾線程池:
newCachedThreadPool
newFixedThreadPool
newSingleThreadExecutor
newScheduledThreadPool
你可以通過Executors來實例化這四種線程池。
查看源碼會發現,這四種線程池都直接或者間接獲取的ThreadPoolExecutor實例 ,只是實例化時傳遞的參數不一樣。所以如果java提供的四種線程池滿足不了我們的需求,我們可以創建自定義線程池。
ThreadPoolExecutor的構造方法如下:
 
public ThreadPoolExecutor(int corePoolSize,
                                      int maximumPoolSize,
                                      long keepAliveTime,
                                      TimeUnit unit,
                                      BlockingQueue<Runnable> workQueue,
                                      ThreadFactor threadFactory,
                                      RejectdExecutionHandler handler)

 其中:
corePoolSize: 核心池的大小。 當有任務來之后,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中
maximumPoolSize: 線程池最大線程數,它表示在線程池中最多能創建多少個線程;
keepAliveTime: 表示線程沒有任務執行時最多保持多久時間會終止。
unit: 參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:

  1. TimeUnit.DAYS; //天
  2. TimeUnit.HOURS; //小時
  3. TimeUnit.MINUTES; //分鍾
  4. TimeUnit.SECONDS; //秒
  5. TimeUnit.MILLISECONDS; //毫秒
  6. TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //納秒
 
workQueue: 一個阻塞隊列,用來存儲等待執行的任務。 一般來說,這里的阻塞隊列有以下幾種選擇:
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue
threadFactory: 線程工廠,主要用來創建線程;
handler: 表示當拒絕處理任務時的策略,有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)
ThreadPoolExecutor.CallerRunsPolicy:只要線程池不關閉,該策略直接在調用者線程中,運行當前被丟棄的任務
個人認為這4中策略不友好,最好自己定義拒絕策略,實現RejectedExecutionHandler接口

以下主要講解存儲等待執行的任務的隊列對線程池執行的影響。
以下主要講解存儲等待執行的任務的隊列對線程池執行的影響。

一.有界隊列

1.初始的poolSize < corePoolSize,提交的runnable任務,會直接做為new一個Thread的參數,立馬執行 。
2.當提交的任務數超過了corePoolSize,會將當前的runable提交到一個block queue中,。
3.有界隊列滿了之后,如果poolSize < maximumPoolsize時,會嘗試new 一個Thread的進行救急處理,立馬執行對應的runnable任務。
4.如果3中也無法處理了,就會走到第四步執行reject操作。
public class ThreadPoolExcutorTest implements Runnable {
	public String name;
	public ThreadPoolExcutorTest(String name) {
    	        this.name = name;
	}

	@Override
	public void run() {
		System.out.println(name);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(3);
		ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
							1, //corePoolSize
							2,	//maximumPoolSize
							1L,
							TimeUnit.SECONDS,
							workQueue
							);
		threadPool.execute(new ThreadPoolExcutorTest("任務1"));
		threadPool.execute(new ThreadPoolExcutorTest("任務2"));
		threadPool.execute(new ThreadPoolExcutorTest("任務3"));
		threadPool.execute(new ThreadPoolExcutorTest("任務4"));
		threadPool.execute(new ThreadPoolExcutorTest("任務5"));
		threadPool.execute(new ThreadPoolExcutorTest("任務6"));
		threadPool.shutdown();

	}
 
}                
執行結果是:

二.無界隊列

與有界隊列相比,除非系統資源耗盡,否則無界的任務隊列不存在任務入隊失敗的情況。當有新的任務到來,系統的線程數小於corePoolSize時,則新建線程執行任務。當達到corePoolSize后,就不會繼續增加,若后續仍有新的任務加入,而沒有空閑的線程資源,則任務直接進入隊列等待。若任務創建和處理的速度差異很大,無界隊列會保持快速增長,直到耗盡系統內存。
public class ThreadPoolExcutorTest2 implements Runnable {
	public Integer count;
	public ThreadPoolExcutorTest2(Integer count) {
		this.count= count;
	}
	@Override
	public void run() {
		System.out.println("任務" + count);
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) throws InterruptedException {
		BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
		ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS, workQueue);
		for (int i = 1; i <= 20; i++) {
			pool.execute(new ThreadPoolExcutorTest2(i));
		}
		Thread.sleep(1000);
		System.out.println("線程池中隊列中的線程數量:" + workQueue.size());
	
		pool.shutdown();

	}
}
如果修改了線程池的maximumPoolSize參數(大於corePoolSize的大小),程序執行結果不受影響。所以對於無界隊列,maximumPoolSize的設置設置的再大對於線程的執行是沒有影響的。
Ps:這里說LinkedBlockingQueue是無界隊列是不恰當的,只不過如果用無參構造函數初始化,默認的容量是Integer.MAX_VALUE

總結:

可以用以下一句總結:
當線程池的任務緩存隊列已滿並且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕策略。


免責聲明!

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



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