Thread 指定未受检查处理器 Thread.UncaughtExceptionHandler

Thread 方式指定未受检查的异常

啥叫为受检查异常呢?
定义: 程序运行的时候抛出且没有被程序捕获的异常或者错误。

定义自定的线程未受检查的异常处理器
public class UEHlogger implements Thread.UncaughtExceptionHandler{

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Logger logger = Logger.getAnonymousLogger();
        logger.log(Level.SEVERE,"捕获未受检的异常,线程名称:"+t.getName());
        logger.log(Level.SEVERE,"线程发生中断,线程名称:"+t.getName(),e);
    }
}
测试 用线程池设置

setDefaultUncaughtExceptionHandler() // 设置全局的默认未捕获错误信息代码
setUncaughtExceptionHandler() //设置当前线程的未捕获错误信息代码

使用线程池的时候请使用execute 执行而不是submit,因为submit执行的时候会使得,异常将会被包装,无法先上抛出,除非使用返回Future的get()方法才会,将异常信息返回

同时UncaughtExceptionHandler也将会失败

public class TestMain {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        UEHlogger handler=new UEHlogger();

        User user=null;
        Thread thread=new Thread(new Runnable() {

            Throwable throwable=null;

            @Override
            public void run() {
                try{
                    //认为制作除0异常
                    int result=8/0;
                }catch ( Throwable e){
                    //退出线程
                    System.out.println("捕获到受检查异常......"+e.getMessage());
                }
                //再次抛出未检查的异常,测试异常处理器
                   // user.setName("空指针异常");

                //测试能否继续执行
                System.out.println("我还能执行=========");
            }
        });

        //指定线程抛出异常以后应该如果处理
        thread.setUncaughtExceptionHandler(handler);

        //启动线程执行
        thread.start();

        //线程池测试
        ExecutorService executorService =new ThreadPoolExecutor(2, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                Thread.setDefaultUncaughtExceptionHandler(handler);
                try{
                    //认为制作除0异常
                    int result=8/0;
                }catch ( Throwable e){
                    //退出线程
                    System.out.println("捕获到受检查异常......"+e.getMessage());
                }
                //再次抛出未检查的异常,测试异常处理器
                user.setName("空指针异常");

                //测试能否继续执行
                System.out.println("我还能执行=========");
            }
        });


        //
        Integer result=null;
        Callable<Integer> callable=()->{
            System.out.println("=====进入callAble");
            return 99/0;
        };
        Future<Integer> submit = executorService.submit(callable);
        //使用submit的方式如果有异常时不会显示出来的
        submit.get();
        executorService.shutdown();
    }


    class User{
        private String name;

        private Integer age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

也可以通过ThreadFactoryBuilder 指定未受检查异常处理器

在这里插入图片描述

无论是Callable还是Runable 都是如此

public class submit {

    public static void main(String[] args) {


        //自定一线程未捕获一异常处理器
        UEHlogger handler=new UEHlogger();

        //线程池测试
        ExecutorService executorService =new ThreadPoolExecutor(2, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());
        //
        Integer result=null;
        Callable<Integer> callable=()->{
            Thread.setDefaultUncaughtExceptionHandler(handler);

            System.out.println("=====进入callAble");
            //设置及未捕获异常处理器
            return 99/0;
        };
        Future<Integer> submit = executorService.submit(callable);
        //使用submit的方式如果有异常时不会显示出来的
        try {
            submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally {
            executorService.shutdown();
        }
    }
}

原因分析

为什么会这样呢?查看 FutureTask 源码可以发现,在执行任务出现异常之后,异常存到了一个 outcome 字段中,只有在调用 get 方法获取 FutureTask 结果的时候,才会以 ExecutionException 的形式重新抛出异常

public void run() {
...
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
...
}

protected void setException(Throwable t) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = t;
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
        finishCompletion();
    }
}

public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}

private V report(int s) throws ExecutionException {
    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值