多线程异常捕获

1.多线程常用方式

  • 创建Thread
  • 使用线程池

2.实现接口

  • Runnable,无返回值
  • Callable,可有返回值

3.异常捕获

线程运行过程中发生的异常,无法通过try catch方式,在外层进行捕获,例如

	try {
          new Thread(new Runnable() {
                @Override
                public void run() {
                    int i = 1 / 0;
                }
            }).start();
        } catch (Exception e) {
            System.out.println("error");
        }

执行上面的代码,你会发现,error永远不会打印在你的控制台或是log中,原因为何,没去深究,不过我想大概是因为线程有自己独立的栈区

4.如何捕获异常

  • 创建Thread方式 使用UncaughtExceptionHandler方式捕获运行时异常
try {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            int i = 1 / 0;
        }
    });
    thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("uncaughtException");
        }
    });
    thread.start();
} catch (Exception e) {
    System.out.println("error");
}
  • 使用线程池方式 通常我们都会使用concurrent包中的一些工具类来创建使用线程池,Executors为我们提供了几种线程池,但是底层实现其实都是使用ThreadPoolExecutor,ThreadPoolExecutor预留了方法afterExecute可以让我们实现线程内异常的处理
private static ThreadPoolExecutor executorPool = new ThreadPoolExecutor(4, 20,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1),
            new SimpleThreadFactory("executor"),
            new CustomRejectedExecutionHandler()
    ) {
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            if (t == null && r instanceof Future<?>) {
                try {
                    Object result = ((Future<?>) r).get();
                } catch (CancellationException ce) {
                    t = ce;
                } catch (ExecutionException ee) {
                    t = ee.getCause();
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt(); // ignore/reset
                }
            }
            if (t != null) {
                System.out.println("t is :" + t);
                t.printStackTrace();
            }
        }
    };

这样就可以在异常发生时,可以打印出异常信息,而不是被吃掉

5.被吃掉的原因

我们在sumbit任务到ThreadPool时,自动为我们包装成了FutureTask,而FutureTask对象在执行时,是会把异常吃掉,直到我们get FutureTask的执行结果时才会把异常抛出。相关的代码如下:

转载于:https://my.oschina.net/zjoschina/blog/611433

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值