Java技術:使您輕鬆地進行多執行緒應用程式程式設計(2)(轉)
Java技術:使您輕鬆地進行多執行緒應用程式程式設計(2)(轉)[@more@]使用 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.isInterrupted())
{
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 將大多數時間用於編寫基礎結構程式碼和解決難題。可以透過 與他聯絡。
Ze´ev Bubis 是 GlobaLoop LTD 一個軟體開發小組的負責人。Ze´ev 擁有 Tel-Aviv 大學電腦科學及數學學士學位。最近 10 年,他一直從事軟體開發,在此期間,他為多種平臺和語言編寫軟體應用程式。最近三年中,Ze´ev 專注於用 Java 開發客戶機和伺服器應用程式。可以透過 與他聯絡。
清單 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.isInterrupted())
{
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 將大多數時間用於編寫基礎結構程式碼和解決難題。可以透過 與他聯絡。
Ze´ev Bubis 是 GlobaLoop LTD 一個軟體開發小組的負責人。Ze´ev 擁有 Tel-Aviv 大學電腦科學及數學學士學位。最近 10 年,他一直從事軟體開發,在此期間,他為多種平臺和語言編寫軟體應用程式。最近三年中,Ze´ev 專注於用 Java 開發客戶機和伺服器應用程式。可以透過 與他聯絡。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-958477/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【Java多執行緒】輕鬆搞定Java多執行緒(二)Java執行緒
- 多執行緒程式設計(轉)執行緒程式設計
- Java多執行緒程式設計入門(轉)Java執行緒程式設計
- Java多執行緒程式設計——進階篇一Java執行緒程式設計
- Java多執行緒程式設計——進階篇二Java執行緒程式設計
- java多執行緒程式設計chap1-2Java執行緒程式設計
- Java程式中的多執行緒(2)(轉)Java執行緒
- DELPHI下的多執行緒程式設計(2) (轉)執行緒程式設計
- .NET多執行緒程式設計(3):執行緒同步 (轉)執行緒程式設計
- 深入淺出Java多執行緒程式設計(轉)Java執行緒程式設計
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- 程式設計思想之多執行緒與多程式(3):Java 中的多執行緒程式設計執行緒Java
- 淺析Java多執行緒程式設計中的高階技術Java執行緒程式設計
- POSIX執行緒程式設計起步(2)-執行緒同步 (轉)執行緒程式設計
- java執行緒程式設計(一):執行緒基礎(轉)Java執行緒程式設計
- .NET多執行緒程式設計(4):執行緒池和非同步程式設計 (轉)執行緒程式設計非同步
- 多執行緒程式設計執行緒程式設計
- Java多執行緒程式設計基礎Java執行緒程式設計
- Java多執行緒程式設計要點Java執行緒程式設計
- 《Java 多執行緒程式設計核心技術》筆記——第3章 執行緒間通訊(三)Java執行緒程式設計筆記
- 《Java 多執行緒程式設計核心技術》筆記——第3章 執行緒間通訊(四)Java執行緒程式設計筆記
- 在Web應用程式中執行計劃任務(多執行緒) (轉)Web執行緒
- Java核心技術學習筆記——進階——第五章 Java多執行緒和併發程式設計——5.2 Java多執行緒實現Java筆記執行緒程式設計
- Java多執行緒程式設計筆記2:synchronized同步方法Java執行緒程式設計筆記synchronized
- 程式設計思想之多執行緒與多程式(2):執行緒優先順序與執行緒安全程式設計執行緒
- Java多執行緒程式設計—鎖優化Java執行緒程式設計優化
- Java-基礎程式設計-多執行緒Java程式設計執行緒
- java多執行緒程式設計--基礎篇Java執行緒程式設計
- Java多執行緒程式設計要點 (一)Java執行緒程式設計
- Java 多執行緒程式設計要點(synchronized)Java執行緒程式設計synchronized
- 使用Java實現多執行緒程式設計Java執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Boost多執行緒程式設計執行緒程式設計
- UNIX多執行緒程式設計執行緒程式設計
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- Posix執行緒程式設計指南(2)-執行緒私有資料 (轉)執行緒程式設計
- Linux下應用程式開發:QT中的多執行緒程式設計(轉)LinuxQT執行緒程式設計
- C++ Builder 多執行緒程式設計技術經驗談C++UI執行緒程式設計