JDK線程池的使用

直接上代碼了

package cn.gaialine.threadpool;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.TimeUnit;

/**
 * 線程池測試用例
 * @author yangyong
 *
 */
public class TestThreadPool {
	//線程池維護線程的最少數量
	private static final int COREPOOLSIZE = 2;
	//線程池維護線程的最大數量
	private static final int MAXINUMPOOLSIZE = 5;
	//線程池維護線程所允許的空閒時間
	private static final long KEEPALIVETIME = 4;
	//線程池維護線程所允許的空閒時間的單位
	private static final TimeUnit UNIT = TimeUnit.SECONDS;
	//線程池所使用的緩衝隊列,這裏隊列大小爲3
	private static final BlockingQueue<Runnable> WORKQUEUE = new ArrayBlockingQueue<Runnable>(3);
	//線程池對拒絕任務的處理策略:AbortPolicy爲拋出異常;CallerRunsPolicy爲重試添加當前的任務,他會自動重複調用execute()方法;DiscardOldestPolicy爲拋棄舊的任務,DiscardPolicy爲拋棄當前的任務
	private static final AbortPolicy HANDLER = new ThreadPoolExecutor.AbortPolicy();

	public static void main(String[] args) {
		// TODO 初始化線程池
		ThreadPoolExecutor threadPool = new ThreadPoolExecutor(COREPOOLSIZE, MAXINUMPOOLSIZE, KEEPALIVETIME, UNIT, WORKQUEUE, HANDLER);
		for (int i = 1; i < 11; i++) {
			String task = "task@"+i;
			System.out.println("put->"+task);
			//一個任務通過 execute(Runnable)方法被添加到線程池,任務就是一個 Runnable類型的對象,任務的執行方法就是 Runnable類型對象的run()方法
			//處理任務的優先級爲:核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務
			//設此時線程池中的數量爲currentPoolSize,若currentPoolSize>corePoolSize,則創建新的線程執行被添加的任務,
			//當corePoolSize+workQueue>currentPoolSize>=corePoolSize,新增任務被放入緩衝隊列,
			//當maximumPoolSize>currentPoolSize>=corePoolSize+workQueue,建新線程來處理被添加的任務,
			//當currentPoolSize>=maximumPoolSize,通過 handler所指定的策略來處理新添加的任務
			//本例中可以同時可以被處理的任務最多爲maximumPoolSize+WORKQUEUE=8個,其中最多5個在線程中正在處理,3個在緩衝隊列中等待被處理
			//當currentPoolSize>corePoolSize時,如果某線程空閒時間超過keepAliveTime,線程將被終止。這樣,線程池可以動態的調整池中的線程數
			threadPool.execute(new ThreadPoolTask(task));
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		threadPool.shutdown();//關閉主線程,但線程池會繼續運行,直到所有任務執行完纔會停止。若不調用該方法線程池會一直保持下去,以便隨時添加新的任務
	}
}



package cn.gaialine.threadpool;

import java.io.Serializable;

/**
 * 任務task
 * @author yangyong
 *
 */
public class ThreadPoolTask implements Runnable,Serializable{
	private static final long serialVersionUID = -8568367025140842876L;

	private Object threadPoolTaskData;
	private static int produceTaskSleepTime = 10000;
	
	public ThreadPoolTask(Object threadPoolTaskData) {
		super();
		this.threadPoolTaskData = threadPoolTaskData;
	}

	public void run() {
		// TODO Auto-generated method stub
		System.out.println("start..."+threadPoolTaskData);
		try {
			//模擬線程正在執行任務
			Thread.sleep(produceTaskSleepTime);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("stop..."+threadPoolTaskData);
		threadPoolTaskData = null;
	}
	
	public Object getTask(){
		return this.threadPoolTaskData;
	}
}


執行測試,每1秒添加一個任務,每個任務執行10秒,查看打印數據

put->task@1
start...task@1
put->task@2
start...task@2
put->task@3
put->task@4
put->task@5
put->task@6
start...task@6
put->task@7
start...task@7
put->task@8
start...task@8
put->task@9
Exception in thread "main" java.util.concurrent.RejectedExecutionException
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.reject(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
	at cn.gaialine.threadpool.TestThreadPool.main(TestThreadPool.java:42)
stop...task@1
start...task@3
stop...task@2
start...task@4
stop...task@6
start...task@5
stop...task@7
stop...task@8
stop...task@3
stop...task@4
stop...task@5
從中可以看出task1和task2依次最先執行,這時候currentPoolSize=2達到了corePoolSize,task3、task4、task5被送入緩衝隊列,達到了workQueue最大值3,task6、task7、task8開啓新的線程開始執行,此時currentPoolSize=5達到了maximumPoolSize,task9、task10根據AbortPolicy策略拋出異常,不再執行task9和task10。10秒鐘後task1、task2....依次執行完畢釋放線程,開始執行隊列裏的task3、task4、task5,最後task3、4、5執行完畢,所有任務完成


JDK根據ThreadPoolExecutor配置好的線程池

    // 固定工作線程數量的線程池
    ExecutorService executorService1 = Executors.newFixedThreadPool(3);

    // 一個可緩存的線程池
    ExecutorService executorService2 = Executors.newCachedThreadPool();

    // 單線程化的Executor
    ExecutorService executorService3 = Executors.newSingleThreadExecutor();

    // 支持定時的以及週期性的任務執行
    ExecutorService executorService4 = Executors.newScheduledThreadPool(3);


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