線程異常處理
異常處理方法:
1.直接在子線程內try-catch,不能通知到主線程
2.不在子線程內try-catch,新建MyUncaughtExceptionHandler 實現Thread.UncaughtExceptionHandler,重寫uncaughtException(Thread t, Throwable e) 處理異常,不能通知到主線程
3.線程任務實現Callable接口,FutureTask包裹線程任務,可在主線程中處理線程異常
4. Executors.callable 可在主線程中處理線程異常
5.Executors.new…()生產ExecutorService executorService ,executorService 調用submit(new MyTask())產生Future實例,可在主線程中處理線程異常
一、主線程try-catch不能捕獲子線程的異常
public class ThreadSon {
public static void main(String[] args) {
Thread thread = null;
try {
thread = new Thread(new MyTask());
} catch (Exception e) {
System.out.println("----主線程捕獲異常: "+e.getMessage());
}
thread.start();
}
static class MyTask implements Runnable{
@Override
public void run() {
try {
System.out.println(1/0);
} catch (Exception e) {
System.out.println("----子線程捕獲異常: "+e.getMessage());
}
}
}
}
輸出:
----子線程捕獲異常: / by zero
Process finished with exit code 0
注:1.異常處理第一種辦法:直接在子線程內try-catch,不能通知到主線程
2.JVM會調用 dispatchUncaughtException 來尋找handler進行處理。而如果沒有自定義hanlder進行處理,則會調用 System.err 進行輸出
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) { // 父級優先處理
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) { // 沒有配置handler時的處理方式
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}
二、MyUncaughtExceptionHandler
package com.wx;
public class ThreadSon {
public static void main(String[] args) {
MyUncaughtExceptionHandler myUncaughtExceptionHandler = new MyUncaughtExceptionHandler();
Thread thread = null;
try {
thread = new Thread(new MyTask());
thread.setUncaughtExceptionHandler(myUncaughtExceptionHandler);
} catch (Exception e) {
System.out.println("----主線程捕獲異常: "+e.getMessage());
}
thread.start();
}
static class MyTask implements Runnable{
@Override
public void run() {
System.out.println(1/0);
}
}
static class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
System.err.println("線程"+t.getName()+"捕獲異常: " + e.getMessage());
}
}
}
輸出:
線程Thread-0捕獲異常: / by zero
Process finished with exit code 0
三、線程任務實現Callable接口,FutureTask包裹線程任務
package com.wx;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadSon2 {
public static void main(String[] args) {
FutureTask<String> stringFutureTask = new FutureTask<>(new MyTask());
Thread thread = new Thread(stringFutureTask);
thread.start();
try {
String s = stringFutureTask.get();
System.out.println("stringFutureTask返回結果:"+s);
} catch (InterruptedException e) {
System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
} catch (ExecutionException e) {
System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
}
}
static class MyTask implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(1/1);
return "succeed";
}
}
}
輸出:
1
stringFutureTask返回結果:succeed
Process finished with exit code 0
如果在MyTask.call()中發送異常,比如:
package com.wx;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadSon2 {
public static void main(String[] args) {
FutureTask<String> stringFutureTask = new FutureTask<>(new MyTask());
Thread thread = new Thread(stringFutureTask);
thread.start();
try {
String s = stringFutureTask.get();
System.out.println("stringFutureTask返回結果:"+s);
} catch (InterruptedException e) {
System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
} catch (ExecutionException e) {
System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
}
}
static class MyTask implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(1/0);
return "succeed";
}
}
}
輸出:
stringFutureTask捕獲異常: java.lang.ArithmeticException: / by zero
Process finished with exit code 0
四、Executors.callable()
import java.util.concurrent.*;
public class ThreadSon3 {
public static void main(String[] args) {
String result = "";
Callable<String> callable = Executors.callable(new MyTask(),result);
try {
callable.call();
} catch (Exception e) {
e.printStackTrace();
}
}
static class MyTask implements Runnable{
@Override
public void run() {
System.out.println(1/0);
}
}
}
輸出:
java.lang.ArithmeticException: / by zero
at com.wx.ThreadSon3$MyTask.run(ThreadSon3.java:20)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at com.wx.ThreadSon3.main(ThreadSon3.java:10)
Process finished with exit code 0
五、Future
package com.wx;
import java.util.concurrent.*;
public class ThreadSon4 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<?> future = executorService.submit(new MyTask());
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
if (executorService!=null) {
executorService.shutdown();
}
}
}
static class MyTask implements Runnable{
@Override
public void run() {
System.out.println(1/0);
}
}
}
輸出
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.wx.ThreadSon4.main(ThreadSon4.java:10)
Caused by: java.lang.ArithmeticException: / by zero
at com.wx.ThreadSon4$MyTask.run(ThreadSon4.java:26)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 0