注意異步方法並沒有指定返回值因為其句柄將被立即返回而不用等到請求的操作處理完成後所以此時沒有合理的返回值對於派生出的模型$task 關鍵字和 class 一樣同效 $task 可以實現接口繼承類和繼承的其它任務標有 asynchronous 關鍵字的方法由 $task 在後台處理其它的方法將同步運行就像在類中一樣
$task關鍵字可以用一個可選的 $error 從句修飾 (如上所示)它表明對任何無法被異步方法本身捕捉的異常將有一個缺省的處理程序我使用 $ 來代表被拋出的異常對象如果沒有指定 $error 從句就將打印出一個合理的出錯信息(很可能是堆棧跟蹤信息)
注意為確保線程安全異步方法的參數必須是不變 (immutable) 的運行時系統應通過相關語義來保證這種不變性(簡單的復制通常是不夠的)
所有的 task 對象必須支持一些偽信息 (pseudomessage)
除了常用的修飾符(public 等)task 關鍵字還應接受一個 $pooled(n) 修飾符它導致 task 使用一個線程池而不是使用單個線程來運行異步請求 n 指定了所需線程池的大小必要時此線程池可以增加但是當不再需要線程時它應該縮到原來的大小偽域 (pseudofield) $pool_size 返回在 $pooled(n) 中指定的原始 n 參數值
在《Taming Java Threads 》的第八章中我給出了一個服務器端的 socket 處理程序作為線程池的例子它是關於使用線程池的任務的一個好例子其基本思路是產生一個獨立對象它的任務是監控一個服務器端的 socket每當一個客戶機連接到服務器時服務器端的對象會從池中抓取一個預先創建的睡眠線程並把此線程設置為服務於客戶端連接socket 服務器會產出一個額外的客戶服務線程但是當連接關閉時這些額外的線程將被刪除
Socket_server對象使用一個獨立的後台線程處理異步的 listen() 請求它封裝 socket 的接受循環當每個客戶端連接時 listen() 請求一個 Client_handler 通過調用 handle() 來處理請求每個 handle() 請求在它們自己的線程中執行(因為這是一個 $pooled 任務)
注意每個傳送到$pooled $task 的異步消息實際上都使用它們自己的線程來處理典型情況下由於一個 $pooled $task 用於實現一個自主操作所以對於解決與訪問狀態變量有關的潛在的同步問題最好的解決方法是在 $asynchronous 方法中使用 this 是指向的對象的一個獨有副本這就是說當向一個 $pooled $task 發送一個異步請求時將執行一個 clone() 操作並且此方法的 this 指針會指向此克隆對象線程之間的通信可通過對 static 區的同步訪問實現
改進synchronized
雖然在多數情況下$task 消除了同步操作的要求但是不是所有的多線程系統都用任務來實現所以還需要改進現有的線程模塊 synchronized 關鍵字有下列缺點 無法指定一個超時值 無法中斷一個正在等待請求鎖的線程 無法安全地請求多個鎖 (多個鎖只能以依次序獲得)
解決這些問題的辦法是擴展synchronized 的語法使它支持多個參數和能接受一個超時說明(在下面的括弧中指定)下面是我希望的語法
TimeoutException是 RuntimeException 派生類它在等待超時後即被拋出
超時是需要的但還不足以使代碼強壯您還需要具備從外部中止請求鎖等待的能力所以當向一個等待鎖的線程傳送一個interrupt() 方法後此方法應拋出一個 SynchronizationException 對象並中斷等待的線程這個異常應是 RuntimeException 的一個派生類這樣不必特別處理它
對synchronized 語法這些推薦的更改方法的主要問題是它們需要在二進制代碼級上修改而目前這些代碼使用進入監控(entermonitor)和退出監控(exitmonitor)指令來實現 synchronized 而這些指令沒有參數所以需要擴展二進制代碼的定義以支持多個鎖定請求但是這種修改不會比在 Java 中修改 Java 虛擬機的更輕松但它是向下兼容現存的 Java 代碼
另一個可解決的問題是最常見的死鎖情況在這種情況下兩個線程都在等待對方完成某個操作
[] [] [] [] [] [] []
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27692.html