Java多執行緒設計模式之執行緒池模式
前序:
Thread-Per-Message Pattern,是一種對於每個命令或請求,都分配一個執行緒,由這個執行緒執行工作。它將“委託訊息的一端”和“執行訊息的一端”用兩個不同的執行緒來實現。該執行緒模式主要包括三個部分:
1,Request參與者(委託人),也就是訊息傳送端或者命令請求端
2,Host參與者,接受訊息的請求,負責為每個訊息分配一個工作執行緒。
3,Worker參與者,具體執行Request參與者的任務的執行緒,由Host參與者來啟動。
由於常規呼叫一個方法後,必須等待該方法完全執行完畢後才能繼續執行下一步操作,而利用執行緒後,就不必等待具體任務執行完畢,就可以馬上返回繼續執行下一步操作。
背景:
由於在Thread-Per-Message Pattern中對於每一個請求都會生成啟動一個執行緒,而執行緒的啟動是很花費時間的工作,所以鑑於此,提出了Worker Thread,重複利用已經啟動的執行緒。
執行緒池:
Worker Thread,也稱為工人執行緒或背景執行緒,不過一般都稱為執行緒池。該模式主要在於,事先啟動一定數目的工作執行緒。當沒有請求工作的時候,所有的工人執行緒都會等待新的請求過來,一旦有工作到達,就馬上從執行緒池中喚醒某個執行緒來執行任務,執行完畢後繼續線上程池中等待任務池的工作請求的到達。
任務池:主要是儲存接受請求的集合,利用它可以緩衝接受到的請求,可以設定大小來表示同時能夠接受最大請求數目。這個任務池主要是供執行緒池來訪問。
執行緒池:這個是工作執行緒所在的集合,可以通過設定它的大小來提供併發處理的工作量。對於執行緒池的大小,可以事先生成一定數目的執行緒,根據實際情況來動態增加或者減少執行緒數目。執行緒池的大小不是越大越好,執行緒的切換也會耗時的。
存放池的資料結構,可以用陣列也可以利用集合,在集合類中一般使用Vector,這個是執行緒安全的。
Worker Thread的所有參與者:
1,Client參與者,傳送Request的參與者
2,Channel參與者,負責快取Request的請求,初始化啟動執行緒,分配工作執行緒
3,Worker參與者,具體執行Request的工作執行緒
4,Request參與者
注意:將在Worker執行緒內部等待任務池非空的方式稱為正向等待。
將在Channel執行緒提供Worker執行緒來判斷任務池非空的方式稱為反向等待。
執行緒池例項1:
利用同步方法來實現,使用陣列來作為任務池的存放資料結構。在Channel有快取請求方法和處理請求方法,利用生成者與消費者模式來處理儲存請求,利用反向等待來判斷任務池的非空狀態。
Channel參與者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package whut.threadpool;
//用到了生產者與消費者模式
//生成執行緒池,接受客戶端執行緒的請求,找到一個工作執行緒分配該客戶端請求
public class Channel
{
private static final int MAX_REQUEST
= 100 ; //
併發數目,就是同時可以接受多少個客戶端請求
//利用陣列來存放請求,每次從陣列末尾新增請求,從開頭移除請求來處理
private final Request[]
requestQueue; //
儲存接受客戶執行緒的數目
private int tail; //下一次存放Request的位置
private
|