使用UncaughtExceptionHandler重啓線程

咱們已經知道,Java中有兩種異常,即已檢測異常和未檢測異常。已檢測的異常必須在拋出語句(throws clause)的方法中指定或者捕獲。未檢測的異常不須要指定或捕獲。由於run()方法不接受拋出語句,因此當一個檢測的異常在一個Thread對象的 run()方法中拋出,咱們須要對其進行捕獲並作相應的處理。可是當一個未檢測的異常在一個線程的run()方法中拋出,默認的行爲是將堆棧跟蹤信息寫到 控制檯中(或者記錄到錯誤日誌文件中)而後退出程序。html

幸運的是,Java爲咱們提供了一個機制,用來捕獲並處理在一個線程對象中拋出的未檢測異常,以免程序終止。咱們能夠經過UncaughtExceptionHandler來實現這種機制。java

讓咱們來作個UncaughtExceptionHandler的使用 示例。在這個例子中,咱們已經建立一個線程,這個線程嘗試解析一些原本應該是整數的字符串。咱們已經寫出run()方法,讓它在執行時拋出 java.lang.NumberFormatException。當程序不去捕獲異常時,異常通過JVM的同時線程也被殺死。這確實屬於正常的行爲,但 不是咱們但願看到的。多線程

不使用UncaughtExceptionHandler

在現實生活的應用中,對於一個關鍵的任務,雖然已經失敗了幾回,可是你依然願意嘗試再執行幾回。下面的例子解釋了這個用例,首先不使用UncaughtExceptionHandler時,線程在執行失敗以後當即終止。ide

Task.java學習

1spa

2線程

3翻譯

4rest

5日誌

6

7

8

9

10

11

12

class Task implements Runnable

{

   @Override

   public void run()

   {

      System.out.println(Integer.parseInt("123"));

      System.out.println(Integer.parseInt("234"));

      System.out.println(Integer.parseInt("345"));

      System.out.println(Integer.parseInt("XYZ")); //This will cause NumberFormatException

      System.out.println(Integer.parseInt("456"));

   }

}

DemoThreadExample.java

1

2

3

4

5

6

7

8

9

public class DemoThreadExample

{

   public static void main(String[] args)

   {

      Task task = new Task();

      Thread thread = new Thread(task);

      thread.start();

   }

}

下面是線程運行時的輸出:

1

2

3

4

5

6

7

8

9

123

234

345

Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "XYZ"

    at java.lang.NumberFormatException.forInputString(Unknown Source)

    at java.lang.Integer.parseInt(Unknown Source)

    at java.lang.Integer.parseInt(Unknown Source)

    at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)

    at java.lang.Thread.run(Unknown Source)

使用UncaughtExceptionHandler以後

首先,咱們實現UncaughtExceptionHandler接口,用來捕獲運行時的任意未檢測的異常。

ExceptionHandler.java

1

2

3

4

5

6

7

8

9

10

11

12

13

class ExceptionHandler implements UncaughtExceptionHandler

{

   public void uncaughtException(Thread t, Throwable e)

   {

      System.out.printf("An exception has been capturedn");

      System.out.printf("Thread: %sn", t.getId());

      System.out.printf("Exception: %s: %sn", e.getClass().getName(), e.getMessage());

      System.out.printf("Stack Trace: n");

      e.printStackTrace(System.out);

      System.out.printf("Thread status: %sn", t.getState());

      new Thread(new Task()).start();

   }

}

將異常處理程序添加到線程:

1

2

3

4

5

6

7

8

9

10

11

12

13

class Task implements Runnable

{

   @Override

   public void run()

   {

      Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());

      System.out.println(Integer.parseInt("123"));

      System.out.println(Integer.parseInt("234"));

      System.out.println(Integer.parseInt("345"));

      System.out.println(Integer.parseInt("XYZ")); //This will cause NumberFormatException

      System.out.println(Integer.parseInt("456"));

   }

}

再次運行上面的例子,會發現線程可以持續執行。實際上,若是線程完成了任務,那麼它在退出時不會拋出任何異常,從而完成自身生命週期。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

123

234

345

An exception has been captured

Thread: 1394

Exception: java.lang.NumberFormatException: For input string: "XYZ"

Stack Trace:

java.lang.NumberFormatException: For input string: "XYZ"

    at java.lang.NumberFormatException.forInputString(Unknown Source)

    at java.lang.Integer.parseInt(Unknown Source)

    at java.lang.Integer.parseInt(Unknown Source)

    at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)

    at java.lang.Thread.run(Unknown Source)

Thread status: RUNNABLE

123

234

345

An exception has been captured

Thread: 1395

Exception: java.lang.NumberFormatException: For input string: "XYZ"

Stack Trace:

java.lang.NumberFormatException: For input string: "XYZ"

    at java.lang.NumberFormatException.forInputString(Unknown Source)

    at java.lang.Integer.parseInt(Unknown Source)

    at java.lang.Integer.parseInt(Unknown Source)

    at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)

    at java.lang.Thread.run(Unknown Source)

Thread status: RUNNABLE

123

234

345

上面的程序實現幫你運行一個線程,在完成任務以前,這個線程會持續運行。經過其餘多線程的思想一樣能夠實現這種狀況。

請注意:UncaughtExceptionHandler能夠在無需重啓線程的條件下,將日誌記錄變得更加健壯,由於默認日誌在線程執行失敗時,不會提供足夠的上下文信息。

學習愉快!

原文連接: howtodoinjava 翻譯: ImportNew.com - Angus
譯文連接: http://www.importnew.com/14434.html

相關文章
相關標籤/搜索