在多執行緒中捕獲並處理RuntimeException
阿新 • • 發佈:2019-01-24
在多執行緒的機制下,我們不能跨越執行緒在主執行緒中捕獲其他執行緒的異常。
對於非執行時異常,線上程很多很複雜的時候,為每個執行緒都寫一份異常處理程式也很難過。對於執行時異常,如果我們不能採取一些有用的措施,那麼異常會被丟擲到控制檯上。
比如下面的例子:
package AllThread;
/**
*
* @author QuinnNorris
*
* 捕獲異常
*/
public class ExceptionThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread th = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
throw new RuntimeException();
}
});
th.start();
}
}
這是一段簡單的程式碼,它會丟擲一個執行時異常:
Exception in thread “Thread-0” java.lang.RuntimeException
at AllThread.ExceptionThread$1.run(ExceptionThread.java:15)
at java.lang.Thread.run(Thread.java:745)
我們可以看出, 由於沒有去設計捕獲異常,它被直接輸出到控制檯上。對於這種情況,為main函式加上try-catch語句是沒有用的。
為了增加對異常處理的手段,在JAVA SE5中引入了使用Executor的一種解決方法。
package AllThread;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
*
* @author QuinnNorris
*
* 使用UncaughtExceptionHandler捕獲異常
*/
public class UEHThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService es = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
// TODO Auto-generated method stub
Thread th = new Thread(r);
th.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
System.out.println("catch it " + e);
}
});
return th;
}
});
es.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
throw new RuntimeException();
}
});
}
}
因為我比較懶全部用內部類來表示,所以這段程式可能略有些難懂。
- 首先我們建立了一個執行緒池,然後為這個建立執行緒池的靜態方法賦予一個引數。這個引數是一個ThreadFactory類,這個類是用來描述線上程池中的執行緒具有的共性的。
- ThreadFactory有一個方法需要我們覆蓋就是newThread方法,這個方法的引數是我們要處理的Runnable任務,也就是我們要加入到執行緒池中的Runnable任務。
- 我們在這個方法中用一個th物件包含r物件,然後設定th物件的UncaughtExceptionHandler屬性。
- 這個setUncaughtExceptionHandler方法的引數是一個UncaughtExceptionHandler物件,這裡我們第二次用內部類。
- UncaughtExceptionHandler類的唯一一個方法是uncaughtException。這個方法用來表示對執行緒未檢查異常的處理方式,我們讓他在控制檯輸出一句話。到這裡我們對執行緒池的部署就完成了。
- 然後我們在這個執行緒池中新增一個Runnable任務,這個任務會丟擲一個未檢查異常。
現在我們執行程式,控制檯輸出:
catch it java.lang.RuntimeException
到此,對於執行緒run方法中的未檢查異常的處理就結束了。需要注意的是,我們向執行緒池中新增執行緒的方法要呼叫execute方法而不要使用submit方法,submit方法會把異常吞掉。從而控制檯將會什麼都不輸出。