【捕获Java线程池执行任务抛出的异常】

Java中线程执行的任务接口java.lang.Runnable 要求不抛出Checked异常,

  public interface Runnable {

  public abstract void run();

  }

  那么如果 run() 方法中抛出了RuntimeException,将会怎么处理了?

  通常java.lang.Thread对象运行设置一个默认的异常处理方法:

  java.lang.Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)

  而这个默认的静态全局的异常捕获方法时输出堆栈。

  当然,我们可以覆盖此默认实现,只需要一个自定义的java.lang.Thread.UncaughtExceptionHandler接口实现即可。

  public interface UncaughtExceptionHandler {

  void uncaughtException(Thread t, Throwable e);

  }

  而在线程池中却比较特殊。默认情况下,线程池 java.util.concurrent.ThreadPoolExecutor 会Catch住所有异常, 当任务执行完成(java.util.concurrent.ExecutorService.submit(Callable))获取其结果 时(java.util.concurrent.Future.get())会抛出此RuntimeException。

  /**

  * Waits if necessary for the computation to complete, and then

  * retrieves its result.

  *

  * @return the computed result

  * @throws CancellationException if the computation was cancelled

  * @throws ExecutionException if the computation threw an exception

  * @throws InterruptedException if the current thread was interrupted while waiting

  */

  V get() throws InterruptedException, ExecutionException;

  其中 ExecutionException 异常即是java.lang.Runnable 或者 java.util.concurrent.Callable 抛出的异常。

  也就是说,线程池在执行任务时捕获了所有异常,并将此异常加入结果中。这样一来线程池中的所有线程都将无法捕获到抛出的异常。 从而无法通过设置线程的默认捕获方法拦截的错误异常。

  也不同通过自定义线程来完成异常的拦截。

  好在java.util.concurrent.ThreadPoolExecutor 预留了一个方法,运行在任务执行完毕进行扩展(当然也预留一个protected方法beforeExecute(Thread t, Runnable r)):

  protected void afterExecute(Runnable r, Throwable t) { }

  此方法的默认实现为空,这样我们就可以通过继承或者覆盖ThreadPoolExecutor 来达到自定义的错误处理。

  解决办法如下:

  ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(11, 100, 1, TimeUnit.MINUTES, //

  new ArrayBlockingQueue<Runnable>(10000),//

  new DefaultThreadFactory()) {

  protected void afterExecute(Runnable r, Throwable t) {

  super.afterExecute(r, t);

  printException(r, t);

  }

  };

  private static void printException(Runnable r, Throwable t) {

  if (t == null && r instanceof Future<?>) {

  try {

  Future<?> future = (Future<?>) r;

  if (future.isDone())

  future.get();

  } catch (CancellationException ce) {

  t = ce;

  } catch (ExecutionException ee) {

  t = ee.getCause();

  } catch (InterruptedException ie) {

  Thread.currentThread().interrupt(); // ignore/reset

  }

  }

  if (t != null)

  log.error(t.getMessage(), t);

  }

更多精彩教程请关注: ghost xp sp3 纯净版
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值