2010年9月30日 星期四

[ Java設計模式 ] 多線程設計模式 : Thread-Per-Message Pattern (這個工作交給你了)


前言 :
上司把文件交給下屬, 指示”能幫我傳真這份文件嗎?”, 妻子對先生說”老公, 幫忙倒一下垃圾喔”. 一個人將工作拜託別人去做, 是很常見的事. 拜託別人 “這件事交給你搂” 以後, 就回來繼續做自己的事. 這章要學習的是 Thread-Per-Message Pattern. 解釋過來就是每個消息一個線程. Message 這裡可以看做是 “命令” 或 “請求” 的意思. 對每個命令或請求分配一個線程, 由這個線程執行工作, 這就是 “Thread-Per-Message Pattern.”
在使用 Thread-Per-Message Pattern 時, “委託消息的一方” 與 “執行消息的一端” 會是不同的線程.


Thread-Per-Message Pattern 的所有參予者 :
* Client (委託人) 參予者 :
Client 參予者會對 Host 參予者送出請求. Client 參予者並不知道 Host 參予者會如何實現這個請求. 範例程序中 Clinet 參予者是 Main 類.

* Host 參予者 :
Host 參予者收到 Client 參予者的請求, 會建立新的線程並啟動它. 這個新的線程會使用 Helper 參予者. “處理” 這個請求. 範例程序中, Host 參予者是 Host 類.

* Helper 參予者 :
Helper 參予者會對 Host 參予者提供 處理請求 的功能. Host 建立的線程會使用 Helper 參予者. 範例程序中 Helper 參予者是 Helper 類.
* Thread-Per-Message Pattern 示意圖
 


使用範例 :
在這裡要寫的範例程序中, Main 類會委託 Host 類顯示文字. 而Host 類會啟動線程來處理這項委託工作. 啟動的線程會使用 Helper 類來進行顯示操作.
* Main 類 :
Main 類會建立 Host 物件而後調用 Host 物件的 request 方法, 代碼如下 :
  1. package dp.thread.ch7;  
  2.   
  3. public class Main {  
  4.     public static void main(String args[]) {  
  5.         System.out.println("main BEGIN");  
  6.         Host host = new Host();  
  7.         host.request(10'A');  
  8.         host.request(20'B');  
  9.         host.request(30'C');  
  10.         System.out.println("main END");;  
  11.     }  
  12. }  
* Host 類 :
Host 類中, 在request方法中啟動新的線程. 實際的處理委託操作則由該線程負責. 代碼如下 :
  1. package dp.thread.ch7;  
  2.   
  3. public class Host {  
  4.     private final Helper helper = new Helper();  
  5.   
  6.     public void request(final int count, final char c) {  
  7.         System.out.println("    Request("+count+", "+c+")BEGIN");  
  8.         new Thread() {  
  9.             public void run(){  
  10.                 helper.handle(count, c);  
  11.             }  
  12.         }.start();  
  13.         System.out.println("    Request("+count+", "+c+")END");  
  14.     }      
  15. }  
* Helper 類 :
Helper 類提供了handle 方法, 用來將字符顯示指定次數. 代碼如下 :
  1. package dp.thread.ch7;  
  2.   
  3. public class Helper {  
  4.     public void handle(int count, char c) {  
  5.         System.out.println("    Handle("+count+", "+c+") BEGIN");  
  6.         for(int i=0;i
  7.             slowly();  
  8.             System.out.print(c);  
  9.         }  
  10.         System.out.println("");  
  11.         System.out.println("    Handle("+count+", "+c+") END");  
  12.     }  
  13.   
  14.     private void slowly(){  
  15.         try{  
  16.             Thread.sleep(100);  
  17.         }catch(InterruptedException e){  
  18.             e.printStackTrace();  
  19.         }  
  20.     }  
  21. }  

使用時機 :
* 提升響應性, 降低延遲時間 :
使用 Thread-Message Pattern, Host 參予者對 Client 的響應性會變好, 延遲時間會下降, 尤其是當 handle 的操作很花時間或是 handle的操作需要等待 I/O 時, 效果特別明顯.
* 適合在操作順序無所謂時:
Thread-Message Pattern 中, handle 方法執行的順序, 並不一定是以調用 request 的順序來決定. 所以操作順序有要求時, 不適合使用此Pattern.

* 不需要返回值時:
在此Pattern, request 方法不會等待 handle 方法執行的結果. 也就是說 request 方法拿不到 handle 方法的返回值. 需要得知處理結果時, 可以使用 Future Pattern 應用.
* 在服務器的製作 :
為了使服務器可以用來處理多數請求, 可以使用 Thread-Per-Message Pattern. 客戶端送達請求, 由主線程接收. 而實際處理該請求, 則交給其他線程處理, 服務器的主線程則回到繼續等待其他客戶端請求的狀態.


補充說明 :
1. Future Pattern :
Thread-Per-Message Pattern, 會啟動新的線程來進行處理. 但送出的請求的線程不會等待實際操作完成, 故無法獲取處理結果. 而在 Future Pattern 會事先建立用來存放返回值的物件. 當處理操作完畢的線程結束時, 會將值寫入 Future 參予者. 當送出請求需要用到返回值時, 才用 Future 參予者讀取.

2. Worker Thread Pattern :
Thread-Per-Message Pattern 中, 每個請求都會啟動一個線程. 在 Worker Thread Pattern 中則會預先啟動足夠數量的線程, 並重複使用這些線程, 提升程序的執行效率.
This message was edited 2 times. Last update was at 07/01/2010 17:49:28

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...