国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

當主線程崩潰而其它線程繼續運行時發生什么?

2019-11-18 15:06:42
字體:
來源:轉載
供稿:網友

  內容:
孤線程模式
癥狀
治療和預防措施
總結
參考資料

在多線程代碼中,使用驅動其它線程所負責的動作的單個主線程是常見的。這個主線程發送消息,通常是通過把它們放到一個隊列中,然后其它線程處理這些消息。但是假如主線程拋出一個異常,那么剩余的線程會繼續運行,等待更多輸入到該隊列,導致程序凍結。在診斷 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);
}
}

在諸如這樣的案例中,第二個線程接收用于計算的任何數據完全依靠于第一個線程。因此,不可避免地,假如第一個線程崩潰(而在這個樣本中,肯定是這樣的),那么第二個線程將等待永遠不會到來的更多輸入。現在您知道我為什么把這種錯誤叫做孤線程模式。

癥狀
這種錯誤模式最常見的癥狀是我在前面提到的 ? 即,程序好象凍結了。

其它癥狀可能包括打印到程序標準錯誤和標準輸出的堆棧跟蹤實際停止了。

治療和預防措施
一旦診斷出這種錯誤模式,查找并修復在崩潰線程中的潛在的錯誤是顯然的治療之道。但是預防卻困難得多。

不用說,假如您使用單線程設計就能僥幸成功,那么將可以免除很多頭痛的事情。然而,當程序的性能要求是必須考慮的問題時,就要首先考慮使用多線程設計。

診斷這種崩潰的一個輔助手段是捕捉由各種線程拋出的異常并在退出之前通知該問題的依靠線程。這正是我在清單 2 中所做的。

清單 2. 把錯誤通知給客戶機線程的示例
import java.util.Vector;

public class Server2 extends Thread {
Client2 client;
int counter;

public Server2(Client2 _client) {
this.client = _client;
this.counter = 0;
}

public void run() {
try {
while (counter < 10) {
this.client.queue.addElement(new Integer(counter));
counter++;
}
throw new RuntimeException("counter >= 10");
}
catch (Exception e) {
this.client.interruptFlag = true;
throw new RuntimeException(e.toString());
}
}

public static void main(String[] args) {
Client2 c = new Client2();
Server2 s = new Server2(c);
c.start();
s.start();
}
}

class Client2 extends Thread {
Vector queue;
boolean interruptFlag;

public Client2() {
this.queue = new Vector();
this.interruptFlag = false;
}

public void run() {
while (! interruptFlag) {
if (! (queue.size() == 0)) {
processNextElement();
}
}

// Processes whatever elements remain on the queue before exiting.
while (! (queue.size() == 0)) {
processNextElement();
}
System.out.flush();
}

private void processNextElement() {
Object next = queue.elementAt(0);
queue.removeElementAt(0);
System.out.println(next);
}
}

處理被拋出的異常的其它選項可能是調用 System.exit。這個選項在程序的主線程發生崩潰而其它線程不治理任何臨界資源的時候是有意義的。然而在其它情況下,這可能是危險的。例如,考慮這樣一個示例,其它線程中的一個正在治理一個打開的文件。假如這是實際的情況,那么只是退出程序會導致資源泄漏。

即使在上面的簡單示例中,在 server 線程中調用 System.exit 也會導致 client 未處理其隊列上的任何剩余元素就退出。

事實上,就是這樣的問題促使 Sun 不建議線程的 stop 方法。由于強行停止一個線程會使資源陷入非一致狀態,所以 stop 方法破壞了語言的安全性模型。

想了解 Sun 的更多不建議理由,請參閱參考資料。

總結
這里是本周錯誤模式的總結:

模式:孤線程

癥狀:一個鎖定多線程程序,它具有或不具有將堆棧跟蹤打印到標準錯誤。

致因:多個程序線程一直等待來自某個線程的輸入,而該線程在拋出一個未被捕捉的異常后就退出了。

治療和預防措施:把異常處理代碼放到主線程中以在崩潰來臨之際通知依靠線程。
參考資料

參加本文的討論論壇。

閱讀關于為什么不建議 Thread.stop 的 Sun 的解釋。

Neel V. Kumar 在他的文章“Java 程序中的多線程”(developerWorks,2000 年 3 月)中提供調試多線程 Java 的途徑。

Peter Haggar 的“優化 Java 編程中的并發”(IBM PartnerWorld for Developers)是一份優秀的白皮書,它討論通過執行多線程來并發存取數據會導致的常見問題。

想獲得編寫多線程 Java 程序的介紹,請參閱 Alex Roetter 的文章“編寫多線程 Java 應用程序”(developerWorks,2001 年 2 月)。

想為您的 Java 應用程序中的多線程問題獲得技術幫助,請訪問多線程 Java 編程討論論壇。

Brian Goetz 在他共三部分的系列輕松使用線程中處理困難的線程問題。

JUnit 主頁提供討論程序測試方法的很多有趣文章的鏈接,并提供 JUnit 的最新版本。

利用 Java 調試教程(developerWorks,2001 年 2 月),獲取通用調試技術的幫助。

閱讀 Eric 所有診斷 Java 代碼的文章,其中多數著重討論錯誤模式。

請在 developerWorks Java 技術專區查找更多的 Java 參考資料。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 全州县| 鄱阳县| 台中市| 高雄县| 铜山县| 北安市| 饶平县| 响水县| 海城市| 博兴县| 广河县| 鄂尔多斯市| 榆中县| 杂多县| 凭祥市| 比如县| 陆丰市| 西乌珠穆沁旗| 平安县| 西安市| 大悟县| 景谷| 菏泽市| 梓潼县| 姜堰市| 巧家县| 阆中市| 巧家县| 镇宁| 宁海县| 高唐县| 宣城市| 襄樊市| 衢州市| 迁安市| 揭西县| 三穗县| 阿图什市| 兴安县| 丘北县| 西安市|