从Java ExecutorService捕获线程异常

Chu*_*her 17 java multithreading exception

我正在研究用于并行计算JavaSeis.org的软件开发框架.我需要一个强大的机制来报告线程异常.在开发过程中,了解异常的来源具有很高的价值,因此我想在过度报告方面犯错误.我也希望能够在线程中处理Junit4测试.方法是否合理或有更好的方法吗?

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestThreadFailure {

  public static void main(String[] args) {
    int size = 1;
    ExecutorService exec = Executors.newFixedThreadPool(size);
    ThreadFailTask worker = new ThreadFailTask();
    Future<Integer> result = exec.submit(worker);
    try {
      Integer value = result.get();
      System.out.println("Result: " + value);
    } catch (Throwable t) {
      System.out.println("Caught failure: " + t.toString());
      exec.shutdownNow();
      System.out.println("Stack Trace:");
      t.printStackTrace();
      return;
    }
    throw new RuntimeException("Did not catch failure !!");
  }

  public static class ThreadFailTask implements Callable<Integer> {
    @Override
    public Integer call() {
      int nbuf = 65536;
      double[][] buf = new double[nbuf][nbuf];
      return new Integer((int) buf[0][0]);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Gre*_*tes 20

考虑调用execute(),而不是submit()ExecutorService.一个Thread与调用execute()将调用Thread.UncaughtExceptionHandler时失败.

简单地做一个ThreadFactory能安装Thread.UncaughtExceptionHandler上的所有Threads,然后调用你的工作execute()ExecutorService不是submit().

看看这个相关的堆栈溢出问题.

  • 请注意,如果您的`ExecutorService`实际上是`ScheduledExecutorService`,那么即使您调用`execute()`,也不会再调用`UncaughtExceptionHandler`. (10认同)

Ang*_*jpt 8

我不相信在使用时会有一个标准的"钩子"来解决这些异常submit().但是,如果你需要支持submit()(这听起来合理,假设你使用了a Callable),你总是可以包装Callables和Runnables:

ExecutorService executor = new ThreadPoolExecutor(1, 10, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()) {
    @Override
    public <T> Future<T> submit(final Callable<T> task) {
        Callable<T> wrappedTask = new Callable<T>() {
            @Override
            public T call() throws Exception {
                try {
                    return task.call();
                }
                catch (Exception e) {
                    System.out.println("Oh boy, something broke!");
                    e.printStackTrace();
                    throw e;
                }
            }
        };

        return super.submit(wrappedTask);
    }
};
Run Code Online (Sandbox Code Playgroud)

当然,这种方法只有在你是第一个构建的方法时才有效ExecutorService.此外,请记住覆盖所有三个submit()变体.