當主執行緒崩潰而其它執行緒繼續執行時發生什麼(1)(轉)
當主執行緒崩潰而其它執行緒繼續執行時發生什麼(1)(轉)[@more@]內容:
孤執行緒模式
症狀
治療和預防措施
總結
參考資料
關於作者
對本文的評價
當主執行緒崩潰而其它執行緒繼續執行時發生什麼?
Eric E. Allen()
博士研究生候選人,Rice 大學
2001 年 8 月
在多執行緒程式碼中,使用驅動其它執行緒所負責的動作的單個主執行緒是常見的。這個主執行緒傳送訊息,通常是透過把它們放到一個佇列中,然後其它執行緒處理這些訊息。但是如果主執行緒丟擲一個異常,那麼剩餘的執行緒會繼續執行,等待更多輸入到該佇列,導致程式凍結。在診斷 Java 程式碼的這一部分中,專職 Java 開發者兼兼職捉蟲者 Eric Allen 討論檢測、修復和避免這一錯誤模式。請在討論論壇與作者和其他讀者共享您關於本文的心得。
用多執行緒編寫程式碼對程式設計師大有好處。多執行緒能使程式設計(和程式)進行得快得多,而且程式碼能有效得多地使用資源。然而,跟生活中的很多事情一樣,多執行緒也存在缺點。因為多執行緒程式碼天生是非確定性的,出現錯誤的可能性大得多。而且,確實發生的的錯誤很難重現,因此也更難解決。
孤執行緒模式
Java 程式語言為多執行緒程式碼提供了豐富的支援,包括一項特別有用的功能:能夠在一個執行緒中丟擲一個異常而不影響其它執行緒。但這項功能會導致很多難以跟蹤的錯誤。
快速跟蹤程式碼
清單 1.
一個執行緒之間頻繁通訊的示例程式
清單 2.
演示如何捕捉異常並在退出之前通知問題的依賴執行緒。
從某個執行緒的崩潰中恢復過來是有意義,在此種情況下,這種能力能增加程式的健壯性級別。然而,它也使我們難以判斷這些執行緒之一在什麼時候丟擲了一個異常。因為剩餘的執行緒將繼續執行,所以程式會表現出無響應或凍結程式的徵兆。對執行緒之間頻繁通訊的程式而言尤其如此。
考慮清單 1 所示的示例,其中的一對執行緒透過生產者-消費者模型進行通訊。
清單 1. 一個簡單的、多執行緒的消費者-生產者程式
public class Server extends Thread {
Client client;
int counter;
public Server(Client _client) {
this.client = _client;
this.counter = 0;
}
public void run() {
while (counter < 10) {
this.client.queue.addElement(new Integer(counter));
counter++;
}
throw new RuntimeException("counter >= 10");
}
public static void main(String[] args) {
Client c = new Client();
Server s = new Server(c);
c.start();
s.start();
}
}
class Client extends Thread {
Vector queue;
public Client() {
this.queue = new Vector();
}
public void run() {
while (true) {
if (! (queue.size() == 0)) {
processNextElement();
}
}
}
private void processNextElement() {
Object next = queue.elementAt(0);
queue.removeElementAt(0);
System.out.println(next);
}
}
在諸如這樣的案例中,第二個執行緒接收用於計算的任何資料完全依賴於第一個執行緒。因此,不可避免地,如果第一個執行緒崩潰(而在這個樣本中,肯定是這樣的),那麼第二個執行緒將等待永遠不會到來的更多輸入。現在您知道我為什麼把這種錯誤叫做孤執行緒模式。
症狀
這種錯誤模式最常見的症狀是我在前面提到的 ? 即,程式好象凍結了。
其它症狀可能包括列印到程式標準錯誤和標準輸出的堆疊跟蹤實際停止了。
治療和預防措施
一旦診斷出這種錯誤模式,查詢並修復在崩潰執行緒中的潛在的錯誤是顯然的治療之道。但是預防卻困難得多。
不用說,如果您使用單執行緒設計就能僥倖成功,那麼將可以免除很多頭痛的事情。然而,當程式的效能要求是必須考慮的問題時,就要首先考慮使用多執行緒設計。
孤執行緒模式
症狀
治療和預防措施
總結
參考資料
關於作者
對本文的評價
當主執行緒崩潰而其它執行緒繼續執行時發生什麼?
Eric E. Allen()
博士研究生候選人,Rice 大學
2001 年 8 月
在多執行緒程式碼中,使用驅動其它執行緒所負責的動作的單個主執行緒是常見的。這個主執行緒傳送訊息,通常是透過把它們放到一個佇列中,然後其它執行緒處理這些訊息。但是如果主執行緒丟擲一個異常,那麼剩餘的執行緒會繼續執行,等待更多輸入到該佇列,導致程式凍結。在診斷 Java 程式碼的這一部分中,專職 Java 開發者兼兼職捉蟲者 Eric Allen 討論檢測、修復和避免這一錯誤模式。請在討論論壇與作者和其他讀者共享您關於本文的心得。
用多執行緒編寫程式碼對程式設計師大有好處。多執行緒能使程式設計(和程式)進行得快得多,而且程式碼能有效得多地使用資源。然而,跟生活中的很多事情一樣,多執行緒也存在缺點。因為多執行緒程式碼天生是非確定性的,出現錯誤的可能性大得多。而且,確實發生的的錯誤很難重現,因此也更難解決。
孤執行緒模式
Java 程式語言為多執行緒程式碼提供了豐富的支援,包括一項特別有用的功能:能夠在一個執行緒中丟擲一個異常而不影響其它執行緒。但這項功能會導致很多難以跟蹤的錯誤。
快速跟蹤程式碼
清單 1.
一個執行緒之間頻繁通訊的示例程式
清單 2.
演示如何捕捉異常並在退出之前通知問題的依賴執行緒。
從某個執行緒的崩潰中恢復過來是有意義,在此種情況下,這種能力能增加程式的健壯性級別。然而,它也使我們難以判斷這些執行緒之一在什麼時候丟擲了一個異常。因為剩餘的執行緒將繼續執行,所以程式會表現出無響應或凍結程式的徵兆。對執行緒之間頻繁通訊的程式而言尤其如此。
考慮清單 1 所示的示例,其中的一對執行緒透過生產者-消費者模型進行通訊。
清單 1. 一個簡單的、多執行緒的消費者-生產者程式
public class Server extends Thread {
Client client;
int counter;
public Server(Client _client) {
this.client = _client;
this.counter = 0;
}
public void run() {
while (counter < 10) {
this.client.queue.addElement(new Integer(counter));
counter++;
}
throw new RuntimeException("counter >= 10");
}
public static void main(String[] args) {
Client c = new Client();
Server s = new Server(c);
c.start();
s.start();
}
}
class Client extends Thread {
Vector queue;
public Client() {
this.queue = new Vector();
}
public void run() {
while (true) {
if (! (queue.size() == 0)) {
processNextElement();
}
}
}
private void processNextElement() {
Object next = queue.elementAt(0);
queue.removeElementAt(0);
System.out.println(next);
}
}
在諸如這樣的案例中,第二個執行緒接收用於計算的任何資料完全依賴於第一個執行緒。因此,不可避免地,如果第一個執行緒崩潰(而在這個樣本中,肯定是這樣的),那麼第二個執行緒將等待永遠不會到來的更多輸入。現在您知道我為什麼把這種錯誤叫做孤執行緒模式。
症狀
這種錯誤模式最常見的症狀是我在前面提到的 ? 即,程式好象凍結了。
其它症狀可能包括列印到程式標準錯誤和標準輸出的堆疊跟蹤實際停止了。
治療和預防措施
一旦診斷出這種錯誤模式,查詢並修復在崩潰執行緒中的潛在的錯誤是顯然的治療之道。但是預防卻困難得多。
不用說,如果您使用單執行緒設計就能僥倖成功,那麼將可以免除很多頭痛的事情。然而,當程式的效能要求是必須考慮的問題時,就要首先考慮使用多執行緒設計。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-958041/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 當主執行緒崩潰而其它執行緒繼續執行時發生什麼(2)(轉)執行緒
- 執行緒崩潰為什麼不會導致 JVM 崩潰執行緒JVM
- Java執行緒池核心執行緒用盡後為何優先排隊而不是繼續建立執行緒直至最大執行緒數?Java執行緒
- 保證執行緒在主執行緒執行執行緒
- 主執行緒等待所有其他執行緒執行完畢,然後再繼續執行主執行緒的邏輯,有以下幾種方法可以實現:執行緒
- 執行緒池管理(1)-為什麼需要執行緒池執行緒
- 執行緒1-單執行緒執行緒
- 程式執行緒新解:什麼是程式?什麼是執行緒?執行緒
- 分析為什麼有時在非UI執行緒更新UI會崩潰UI執行緒
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- 【多執行緒與高併發】Java守護執行緒是什麼?什麼是Java的守護執行緒?執行緒Java
- 多執行緒-執行緒控制之休眠執行緒執行緒
- 多執行緒-執行緒控制之加入執行緒執行緒
- 多執行緒-執行緒控制之禮讓執行緒執行緒
- 多執行緒-執行緒控制之中斷執行緒執行緒
- QT 主執行緒子執行緒互相傳值QT執行緒
- Thread 中的 join() 方法的作用是呼叫執行緒等待該執行緒執行完後,再繼續執行thread執行緒
- 什麼是執行緒安全和執行緒不安全執行緒
- redis為什麼用單執行緒不用多執行緒Redis執行緒
- 什麼?一個核同時執行兩個執行緒?執行緒
- 多執行緒-執行緒控制之守護執行緒執行緒
- 這樣執行執行緒是否妥當?執行緒
- 執行緒和執行緒池執行緒
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- Java多執行緒——執行緒Java執行緒
- 執行緒 執行緒池 Task執行緒
- 執行緒與多執行緒執行緒
- 執行緒 (轉)執行緒
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- 多執行緒系列(1),多執行緒基礎執行緒
- Java多執行緒1:程式與執行緒概述Java執行緒
- 什麼時候執行緒不安全?怎樣做到執行緒安全?怎麼擴充套件執行緒安全的類?執行緒套件
- 什麼是Python執行緒?Python執行緒如何建立?Python執行緒
- 當執行時,發生了什麼?
- Java 併發:執行緒、執行緒池和執行器全面教程Java執行緒
- 什麼是多執行緒?Python多執行緒有什麼優勢?執行緒Python
- Java併發 之 執行緒池系列 (1) 讓多執行緒不再坑爹的執行緒池Java執行緒