1. 程式人生 > >java-手撕一個執行緒池

java-手撕一個執行緒池

執行緒池作用

  • 降低資源消耗(重複利用已建立的執行緒)
  • 提高響應速度(任務到達時,不需要等待建立執行緒)
  • 提高執行緒的可管理性(執行緒是稀缺資源,執行緒池可以進行統一分配、調優和監控)

不用執行緒池

如果一個執行緒的時間非常長,就沒必要用執行緒池了(不是不能作長時間操作,而是不宜。),況且我們還不能控制執行緒池中執行緒的開始、掛起、和中止。

Executor執行緒池構造4種執行緒池

Java通過Executors(jdk1.5併發包)提供四種執行緒池 Executor框架的最頂層實現是ThreadPoolExecutor類,Executors工廠類中提供的newScheduledThreadPool、newFixedThreadPool、newCachedThreadPool方法其實也只是ThreadPoolExecutor

的核心建構函式引數不同而已。通過傳入不同的引數,就可以構造出適用於不同應用場景下的執行緒池,那麼它的底層原理是怎樣實現的呢,這篇就來介紹下ThreadPoolExecutor執行緒池的執行過程。

newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。

ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
newCachedThreadPool.execute(new Runable(){
	@Override
	public
void run(){ } });

newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。

//最大三個執行緒的執行緒池
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
newFixedThreadPool.execute(new Runable(){
	@Override
	public void run(){
	}
});

△newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。

ExecutorService newScheduledThreadPool =
Executors.newScheduledThreadPool(); newScheduledThreadPool.execute(new Runable(){ @Override public void run(){ } });

newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。

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

設計一個執行緒池

1)執行緒池管理類[單例設計模式] 主要用於實現建立執行緒和新增執行緒處理的新任務,執行任務以及如何回收已經執行完任務的執行緒。 增加任務的方法(addTask)、批量增加任務的方法(batchAddTask)、得到例項的方法(getInstanse)以及執行任務的方法(execute)

//增加任務的方法
public void addTask(Task task){
	lock.lock();
	taskQueue.add(task);
	taskQueue.notifyAll();
	lock.unlock();
}

//執行任務的方法
public void execute(){
	for(int i=0; i<workThreads.length; i++){
	WorkThread wt = workThreads[i];
	if(wt.isWaiting()){
	new Thread(wt).start();
	break;
	}
}

2)工作執行緒類 執行緒池中的執行緒,也實現了Runnable介面,它主要用於處理任務佇列中的任務。 在run()方法裡面它首先判斷任務佇列裡面是否有任務,如果沒有就等待新任務加入,如果有任務就從任務佇列中取出任務並執行,線上程池中可以設定工作執行緒的個數

while(isRunning){
	lock.lock();
	while(taskQueue.isEmpty()){
		try{
			taskQueue.wait();
		}catch(Exception e){
		}
	}
	task = (Task)taskQueue.remove(0);
	try{
		new Thread(task).start();
	}catch(Exception e){
		e.printStackTrace();
	}
	lock.unlock();
	}
}

3)任務類 定義任務的各種屬性,以及要執行的操作

public class Task implements Runnable{
	public void run(){
	}
}

4)任務佇列 Map、Set以及List 按先來先服務的順序用於存放新加入的任務,以便讓工作執行緒來執行 在文中通過Collections.synchronizedList將其轉換為一個執行緒安全的類。任務佇列定義如下所示:

private List<Task> taskQueue = Collections.synchronizedList(new LinkedList<Task>());