Java 线程池中的异常处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3875739/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 06:13:32  来源:igfitidea点击:

Exception handling in ThreadPools

javaexception-handlingthreadpool

提问by Ivan

I have a ScheduledThreadPoolExecutor that seems to be eating Exceptions. I want my executor service to notify me if a submitted Runnable throws an exception.

我有一个似乎正在吃异常的 ScheduledThreadPoolExecutor。如果提交的 Runnable 引发异常,我希望我的执行程序服务通知我。

For example, I'd like the code below to at the very least print the IndexArrayOutOfBoundsException's stackTrace

例如,我希望下面的代码至少打印 IndexArrayOutOfBoundsException 的 stackTrace

threadPool.scheduleAtFixedRate(
  new Runnable() {
    public void run() {
      int[] array = new array[0];
      array[42] = 5;
    }
  },
  1000,
  1500L,
  TimeUnit.MILLISECONDS);

As a side question. Is there a way to write a general try catch block for a ScheduledThreadPoolExecutor?

作为一个侧面问题。有没有办法为 ScheduledThreadPoolExecutor 编写通用的 try catch 块?

//////////END OF ORIGINAL QUESTION //////////////

//////////原始问题结束//////////////

As suggested the following Decorator works well.

正如所建议的,以下装饰器效果很好。

public class CatcherTask implements Runnable{

    Runnable runMe;

    public CatcherTask(Runnable runMe) {
        this.runMe = runMe;
    }

    public void run() {
        try {
            runMe.run();
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

采纳答案by whiskeysierra

I wrote a small postabout this problem a while ago. You have two options:

不久前我写了一篇关于这个问题的小帖子。您有两个选择:

  1. Use the solutionprovided by Colin Herbert or
  2. use a modified version of Mark Peters solutionbut instead of assigning a UncaughtExceptionHandleryou wrap each submitted runnable into a runnable of your own which executes (calls run) the real runnable inside a try-catch-block.
  1. 使用Colin Herbert 提供的解决方案
  2. 使用 Mark Peters解决方案的修改版本,而不是分配一个,UncaughtExceptionHandler而是将每个提交的 runnable 包装到您自己的 runnable 中,run该 runnable 在 try-catch-block 中执行(调用)真正的 runnable。

EDIT
As pointed out by Mark, it's important to wrap the Runnablepassed to ScheduledExecutorServiceinstead of the one passed to the ThreadFactory.

编辑
正如马克所指出的,重要的是包装Runnable传递给ScheduledExecutorService而不是传递给ThreadFactory.

回答by Mark Peters

Warning: This method is not applicable to scheduledthread pool executors. This answer has been undeleted for its relevance to other thread pool executors. See Willi's answer.

警告:此方法不适用于调度线程池执行程序。由于与其他线程池执行程序的相关性,此答案已被取消删除。见威利的回答

Override the ThreadFactoryto give Threads an UncaughtExceptionHandler:

重写ThreadFactory给线程一个 UncaughtExceptionHandler:

ThreadPoolExecutor exec = new ThreadPoolExecutor...;

exec.setThreadFactory(new ExceptionCatchingThreadFactory(exec.getThreadFactory()));
//go on to submit tasks...


private static class ExceptionCatchingThreadFactory implements ThreadFactory {
    private final ThreadFactory delegate;

    private ExceptionCatchingThreadFactory(ThreadFactory delegate) {
        this.delegate = delegate;
    }

    public Thread newThread(final Runnable r) {
        Thread t = delegate.newThread(r);
        t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                e.printStackTrace();  //replace with your handling logic.
            }
        });
        return t;
    }
}

回答by Michael

Consider adding a static event in your ScheduledThreadPoolExecutorclass that any of your tasks can call if an exception is thrown. That way, you can leverage that event to capture and handle the exceptions that occur within your threads.

考虑在您的ScheduledThreadPoolExecutor类中添加一个静态事件,如果抛出异常,您的任何任务都可以调用该事件。这样,您就可以利用该事件来捕获和处理线程中发生的异常。

回答by Colin Hebert

You can use the get()method from the Futureyou're getting by calling scheduleAtFixedRate(). It will throw an ExecutionExceptionif an exeception occurred during the thread execution.

您可以使用您通过调用获得的get()方法。如果在线程执行期间发生异常,它将抛出一个。FuturescheduleAtFixedRate()ExecutionException

回答by Johan Boberg

You could also use a ThreadPoolTaskSchedulerfrom the Spring Framework, which exposes a method to set an error handler and does all the wrapping for you. The default behavior depends on the type of task:

你也可以使用一个ThreadPoolTaskSchedulerSpring框架,它公开设置错误处理程序的方法,并完成所有的包装给你。默认行为取决于任务类型:

If the provided ErrorHandleris not null, it will be used. Otherwise, repeating tasks will have errors suppressed by default whereas one-shot tasks will have errors propagated by default since those errors may be expected through the returned Future. In both cases, the errors will be logged.

如果提供ErrorHandler的不为空,它将被使用。否则,重复任务默认会抑制错误,而一次性任务默认会传播错误,因为这些错误可能会通过返回的Future. 在这两种情况下,都会记录错误。

If you only want to use the wrapping part and not the TaskScheduleryou can use

如果您只想使用包装部分而不是TaskScheduler您可以使用

TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask)

which the TaskScheduleruses internally.

TaskScheduler内部用途。

回答by mryan

You can subclass ScheduledThreadPoolExecutor and override the afterExecutemethod to handle exceptions and errors for any kind of Runnable that you submit.

您可以子类化 ScheduledThreadPoolExecutor 并覆盖afterExecute方法来处理您提交的任何类型的 Runnable 的异常和错误。