Java技術:使您輕松地進行多線程應用程序編程(2)
發表于:2007-07-14來源:作者:點擊數:
標簽:
使用 wait() 和 notify() 機制來完成“睡眠”和“踢”。實際的消費者工作由 OnConsume(Object) 方法處理,如清單 3 所示: 清單 3. 喚醒和通知 Consumer /** * Add an object to the Consumer. * This is the entry point for the producer. * After the ite
使用 wait() 和 notify() 機制來完成“睡眠”和“踢”。實際的消費者工作由 OnConsume(Object) 方法處理,如清單 3 所示:
清單 3. 喚醒和通知 Consumer
/**
* Add an object to the Consumer.
* This is the entry point for the producer.
* After the item is added, the Consumer´s thread
* will be notified.
*
* @param the object to be ´consumed´ by this consumer
*/
public void add(Object o)
{
_queue.add(o);
kickThread();
}
/**
* Wake up the thread (without adding new stuff to consume)
*
*/
public void kickThread()
{
if (!this._thread.isInter
rupted())
{
synchronized(_waitForJobsMonitor)
{
_waitForJobsMonitor.notify();
}
}
}
示例:MessagesProcessor
為了向您展示 Consumer 類是如何工作的,我們將使用一個簡單示例。MessagesProcessor 類以異步方式處理進入的消息(也就是說,不干擾調用線程)。其工作是在每個消息到來時打印它。MessagesProcessor 具有一個處理到來的消息作業的內部 Consumer。當新作業進入空隊列時,Consumer 調用 processMessage(String) 方法來處理它,如清單 4 所示:
清單 4. MessagesProcessor 類
class MessagesProcessor
{
String _name;
// anonymous inner class that supplies the consumer
// capabilities for the MessagesProcessor
private Consumer _consumer = new Consumer()
{
// that method is called on each event retrieved
protected void onConsume(Object o)
{
if (!(o instanceof String))
{
System.out.println("illegal use, ignoring");
return;
}
MessagesProcesser.this.processMessage((String)o);
}
}.setName("MessagesProcessor").init();
public void gotMessageEvent(String s)
{
_consumer.add(s);
}
private void processMessage(String s)
{
System.out.println(_name+" processed message: "+s);
}
private void terminate()
{
_consumer.terminateWait();
_name = null;
}
MessagesProcessor()
{
_name = "Example Consumer";
}
}
正如您可以從上面的代碼中所看到的,定制 Consumer 相當簡單。我們使用了一個匿名內部類來繼承 Consumer 類,并重載抽象方法 onConsume()。因此,在我們的示例中,只需調用 processMessage。
Consumer 類的高級特性
除了開始時提出的基本
需求以外,我們還為 Consumer 類提供了一些我們覺得有用的高級特性。
事件通知
onThreadTerminate():只在終止 Consumer 前調用該方法。我們出于調試目的覆蓋了這個方法。
goingToRest():只在 Consumer 線程進入休眠前調用該方法(也就是說,只在調用 _waitForJobsMonitor.wait() 之前調用)。只在需要消費者在進入休眠之前處理一批已處理工作的復雜情況中,可能需要這種通知。
終止
terminate():Consumer 線程的異步終止。
terminateWait():設置調用線程一直等待,直到消費者線程實際終止為止。
在我們的示例中,如果使用 terminate() 而不是 terminateWait(),那么將會出現問題,因為在將 _name 設置成空值之后調用 onConsume() 方法。這將導致執行 processMessage 的線程拋出一個 NullPointerException。
結束語:Consumer 類的好處
可在參考資料一節下載 Consumer 類的源代碼。請自由使用源代碼,并按照您的需要擴展它。我們發現將這個類用于多線程應用程序
開發有許多好處:
代碼重用/重復代碼的消除:如果您有 Consumer 類,就不必為您應用程序中的每個實例編寫一個新的消費者。如果在應用程序開發中頻繁使用生產者-消費者方案,這可以很大程度地節省時間。另外,請牢記重復代碼是滋生錯誤的沃土。它還使基本代碼的維護更為困難。
更少錯誤:使用驗證過的代碼是一種防止錯誤的好實踐,尤其是處理多線程應用程序時。因為 Consumer 類已經被調試過,所以它更
安全。消費者還通過在線程和資源之間擔任安全中介來防止與線程相關的錯誤。消費者可以代表其它線程以順序的方式訪問資源。
漂亮、清晰的代碼:使用 Consumer 類有助于我們編寫出更簡單的代碼,這樣的代碼更容易理解和維護。如果我們不使用 Consumer 類,就必須編寫代碼來處理兩種不同的功能:消費邏輯(隊列和線程管理、同步等)和指定消費者的用法或功能的代碼。
多謝 Allot Communications 的 Jonathan Lifton 和 Dov Trietsch 對本文提供的幫助。
參考資料
請單擊本文頂部或底部的討論參與本文的
論壇。
請下載 Consumer 類的源代碼。請自由使用該源代碼,并根據您的需要擴展它。
Alex Roetter 的“Writing multithreaded Java applications”(developerWorks,2001 年 2 月)很好地介紹了使用“Java 線程 API”來開發多線程應用程序。
Brian Goetz 關于多線程的三部分系列文章(developerWorks,2001 年 7 月至 2001 年 9 月)提供了對于多線程應用程序開發中產生的某些公共問題的實用
解決方案。請閱讀整個系列文章:
第 1 部分:“同步不是敵人”
第 2 部分:“減少爭用”
第 3 部分:“有時最好不要共享”
如果 Allen Holub 是國王,那么 Java 語言在對多線程的支持方面將會經歷許多重要的更改。關于這些更改的所有內容,請閱讀他的修改 Java 語言的線程模型的提議(developerWorks,2000 年 10 月)。
Eric Allen 的專欄文章“Diagnosing Java Code:The Orphaned Thread bug pattern”(developerWorks,2001 年 8 月)提供了關于多線程代碼調試的提示。請注意 Eric 在其示例中使用了生產者-消費者方案。
Java Developer Connection 為那些進行線程同步研究的人提供了一條有價值的線索。它的一個關鍵示例使用了生產者-消費者方案。
如何在 Java 應用程序中支持已計劃安排的事件?為了方便實現這一任務,Sun Microsystems 在 JDK 1.3 中引入了新的 Timer API。
Java Developer Connection 的文章“An Introduction to Java Stack Traces”向您展示了如何在堆棧跟蹤中識別和收集線索,以解決您的 Java 軟件問題。
IBM Developer Kit for
Linux,Java 技術版,版本 1.3 提供了對多線程應用程序開發的完整支持。
在 developerWorks Java 技術專區中,關于 Java 編程的每個方面,您都可以找到數百篇文章。
關于作者
Joseph(Saffi)Hartal 是 GlobaLoop LTD 的軟件開發人員。Saffi 擁有 Tel-Aviv 大學計算機科學及數學學士學位和工商管理碩士學位。最近 10 年,他一直從事軟件開發,在此期間,他用 C++ 編寫了實時嵌入代碼,還編寫了 Java 客戶機和
服務器應用程序。Saffi 將大多數時間用于編寫基礎結構代碼和解決難題??梢酝ㄟ^ saffi@myrealbox.com 與他聯系。
Ze´ev Bubis 是 GlobaLoop LTD 一個軟件開發小組的負責人。Ze´ev 擁有 Tel-Aviv 大學計算機科學及數學學士學位。最近 10 年,他一直從事軟件開發,在此期間,他為多種平臺和語言編寫軟件應用程序。最近三年中,Ze´ev 專注于用 Java 開發客戶機和服務器應用程序??梢酝ㄟ^ zee
vb@myrealbox.com 與他聯系。
原文轉自:http://www.anti-gravitydesign.com