JAVA Thread線程異常監控,javathread

來源:互聯網
上載者:User

JAVA Thread線程異常監控,javathread

 

一、情境描述:單線程程式可以用try...catch捕獲程式的異常,而在多線程程式的時候是無法使用try...catch捕獲。

樣本1:多線程發生異常,無法使用try...catch捕獲問題

public class NoCaughtThread  implements Runnable{    @Override    public void run() {        System.out.println(3 / 2);        System.out.println(3 / 0);        System.out.println(3 / 1);    }        public static void main(String[] args) {        try {            Thread thread = new Thread(new NoCaughtThread());            thread.start();        } catch (Exception e) {            System.out.println("==Exception: " + e.getMessage());        }    }}

 運行結果:

1
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
at threadtest.NoCaughtThread.run(NoCaughtThread.java:7)
at java.lang.Thread.run(Thread.java:724)

顯然這並非程式設定異常捕獲,此時try...catch無法捕獲線程的異常。此時,如果線程因為異常而終止執行將無法檢測到異常。究其原因Thread類run()方法是不拋出任何檢查型異常的,而自身卻可能因為一個異常而被中止。

二、解決方式大致有兩種:① 在run()中設定對應的異常處理,主動方法來解決未檢測異常;② Thread類API中提供Interface介面UncaughtExceptionHandler,該介面包含uncaughtException方法,它能檢測出某個未捕獲的異常而終結的情況;

樣本2:主動的檢測異常

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class InitiativeCaught {    public static void main(String[] args) {        InitialtiveThread initialtiveThread = new InitialtiveThread() ;        ExecutorService exec = Executors.newCachedThreadPool();        exec.execute(initialtiveThread);        exec.shutdown();    }}class InitialtiveThread implements Runnable {    @Override    public void run() {        Throwable thrown = null;        try {            System.out.println(3 / 2);            System.out.println(3 / 0);            System.out.println(3 / 1);        } catch (Throwable e) {            thrown = e;        } finally {            threadDeal(this, thrown);        }    }        public void threadDeal(Runnable r, Throwable t) {        System.out.println("==Exception: " + t.getMessage());    }  }

 運行結果:

1
==Exception: / by zero

此時是主動捕獲異常並做處理,得到想要的結果。

 

樣本3:Thread類API中提供UncaughtExceptionHandler介面捕獲異常,要求檢測線程異常,發生異常設定為重複調用三次之後結束線程。

import java.lang.Thread.UncaughtExceptionHandler;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadMonitor implements Runnable {    private int data;                    // 可設定通過構造傳參    private int control = 0;    private static final int MAX = 3;    // 設定重試次數        public ThreadMonitor(int i) {        this.data = i;        }    public ThreadMonitor() {        // TODO Auto-generated constructor stub    }        @Override    public void run() {        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {            @Override            public void uncaughtException(Thread arg0, Throwable e) {                // TODO Auto-generated method stub                System.out.println("==Exception: " + e.getMessage());                String message = e.getMessage();                if( control==MAX ){                    return ;                }else if( "ok".equals(message) ){                    return ;                }else if ( "error".equals(message) ) {                    new Thread() {                        public void run() {                            try {                                System.out.println("開始睡眠。");                                Thread.sleep(1 * 1000);                                control++ ;                                System.out.println("睡眠結束,control: "+ control);                                myTask(data) ;                            } catch (InterruptedException e) {                                e.printStackTrace();                            }                        };                    }.start();                }else{                    return ;                }            }        });                  myTask(data) ;            }        @SuppressWarnings("finally")    public void myTask(int data){        boolean flag = true ;        try {            System.out.println(4 / data);        } catch (Exception e) {            flag = false ;        } finally {            if( flag ){                throw new RuntimeException("ok");            }else{                throw new RuntimeException("error");            }        }    }        public static void main(String[] args) {        ExecutorService exec = Executors.newCachedThreadPool();        ThreadMonitor threadMonitor = new ThreadMonitor(0);        exec.execute(threadMonitor);        exec.shutdown();    }}

 運行結果:

==Exception: error
開始睡眠。
睡眠結束,control: 1
==Exception: error
開始睡眠。
睡眠結束,control: 2
==Exception: error
開始睡眠。
睡眠結束,control: 3
==Exception: error

 

此時,可以正常捕獲線程因除數為零造成的中斷。其中:

(1) 在Thread類API中提供Interface介面UncaughtExceptionHandler,該介面包含一個uncaughtException方法,它能檢測出某個由於未捕獲的異常而終結的情況。定義如下:

UncaughtExceptionHandler介面:  public static interface Thread.UncaughtExceptionHandler

uncaughtException方法: public void uncaughtException(Thread t, Throwable e)

(2) uncaughtException方法會捕獲線程的異常,此時需要覆寫該方法設定自訂的處理方式。

(3) 設定UncaughtExceptionHandler異常處理:

方式一:通過Thread提供的靜態static方法,設定預設異常處理:public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler ux)

方式二:通過方法:public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

(4) UncaughtExceptionHandler異常處理需要設定在run()方法內,否則無法捕獲到線程的異常。

(5) 參考連結:

JAVA下記憶體池啟動程式:http://www.cnblogs.com/zhujiabin/p/5404771.html

JAVA下多線程異常處理:http://blog.csdn.net/u013256816/article/details/50417822 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.