UnSuspendThread 一个假的不中断的线程
一般Thread内while(true),循环内使用try{}cache{}:
new Thread(() -> {
while(true){
try {
System.out.println("线程运行中...");
int a = 1/0;
}catch (Exception e){
printExceptionInfo(Thread.currentThread());
}
}
}).start();
一般异常都可以通过try{}cache(Exception e){}来捕获,然而。。。
当你这么写的时候,有时候程序并不是按照预想的步骤执行的,总有那么几次线程诡异的就结束了。。。
比如:
new Thread(() -> {
while(true){
try {
System.out.println("线程运行中...");
throw new Error("捕获不了吧");
}catch (Exception e){
printExceptionInfo(Thread.currentThread());
}
}
}).start();
线程启动级结束。当然你也可以直接捕捉Exception和Error,就像:
catch (Error | Exception e) {
printExceptionInfo(Thread.currentThread());
}
怎么看都有点怪异
那么,有没有个优雅的方式实现 不中断线程?
java.lang.Thread类里有个接口“UncaughtExceptionHandler”了解下?
既然是个接口,那么使用之前就需要先实现它,比如说这样:
public static class UncaughtExceptionHandlerDemo implements Thread.UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
printExceptionInfo(t);
e.printStackTrace();
System.out.println("重新启动线程...");
t = createUnSuspendThread();
pause(1000);
setDefaultExceptionHandler(t);
t.start();
}
public static void setDefaultExceptionHandler(Thread t){
System.out.println("设置默认异常处理器,do something...");
// 此处可用单例
t.setUncaughtExceptionHandler(new UncaughtExceptionHandlerDemo());
System.out.println("设置默认异常处理器。。。done");
}
}
如果一个Thread对象调用了setUncaughtExceptionHandler方法,并且如果恰好调用方法时传入的参数 是 UncaughtExceptionHandlerDemo对象
那么,当这个Thread对象发生异常时(未捕获异常),就会触发UncaughtExceptionHandlerDemo对象的uncaughtException方法
比如说这样:
public static void main(String[] args) {
Thread thread = createUnSuspendThread();
UncaughtExceptionHandlerDemo.setDefaultExceptionHandler(thread);
thread.start();
}
public static Thread createUnSuspendThread() {
return new Thread(() -> {
System.out.println("抛出异常前。。。");
// int a = 1/0;
throw new Error();
}, "测试线程");
}
在执行main方法的时候,理论上 应该先去找一个叫“createUnSuspendThread”的静态方法,该方法会返回一个Thread对象,然后给这个Thread对象添加一个DefaultexceptionHandler即UncaughtExceptionHandlerDemo对象
然后 这个thread开始运行,运行到"throw new Error()"时,不出意外就应该结束了,
如果你在用调试模式的话,此时程序应该跳到了 UncaughtExceptionHandlerDemo 类的 uncaughtException 方法里,
然后打印信息blablabla,然后又tm创建个Thread对象,然后又tm设置了 UncaughtExceptionHandlerDemo
然后又开始运行 Thread#start 方法了,然后。。。
然后 一个一直报错一直自动重新开启线程的 线程,就这么诞生了。。。
为了凑字数,完整代码给你:
/**
* @Author: wang_z
* @Date: 2019/5/28 14:08
* @Description:
*/
public class UncaughtExceptionHandlerTest {
public static void main(String[] args) {
Thread thread = createUnSuspendThread();
UncaughtExceptionHandlerDemo.setDefaultExceptionHandler(thread);
thread.start();
}
public static Thread createUnSuspendThread() {
return new Thread(() -> {
System.out.println("抛出异常前。。。");
// int a = 1/0;
throw new Error();
}, "测试线程");
}
public static void printExceptionInfo(Thread t){
System.out.println(String.format("线程%s[%d]异常结束,异常信息:", t.getName(), t.getId()));
}
public static void pause(long milles){
try {
Thread.currentThread().sleep(milles);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static class UncaughtExceptionHandlerDemo implements Thread.UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
printExceptionInfo(t);
e.printStackTrace();
System.out.println("重新启动线程...");
t = createUnSuspendThread();
pause(1000);
setDefaultExceptionHandler(t);
t.start();
}
public static void setDefaultExceptionHandler(Thread t){
System.out.println("设置默认异常处理器,do something...");
t.setUncaughtExceptionHandler(new UncaughtExceptionHandlerDemo());
System.out.println("设置默认异常处理器。。。done");
}
}
}