线程池中的异常处理

发布于 2024-09-27 01:02:09 字数 812 浏览 13 评论 0 原文

我有一个 ScheduledThreadPoolExecutor 似乎正在吃异常。我希望我的执行器服务在提交的 Runnable 抛出异常时通知我。

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

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

作为附带问题。有没有办法为 ScheduledThreadPoolExecutor 编写通用的 try catch 块?

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

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

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();
        }
    }
}

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.

For example, I'd like the code below to at the very least print the IndexArrayOutOfBoundsException's 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?

//////////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();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

海之角 2024-10-04 01:02:09

我写了一个小不久前发布了关于此问题的帖子。您有两种选择:

  1. 使用 Colin Herbert 提供的解决方案
  2. 使用修改后的解决方案Mark Peters 解决方案的版本,但不是分配 UncaughtExceptionHandler 将每个提交的 runnable 包装到您自己的 runnable 中,该 runnable 在 try-catch 块内执行(调用 run)真正的 runnable。

编辑
正如 Mark 所指出的,包装传递给 ScheduledExecutorServiceRunnable 而不是传递给 ThreadFactory 的 Runnable 非常重要。

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

  1. Use the solution provided by Colin Herbert or
  2. use a modified version of Mark Peters solution but instead of assigning a UncaughtExceptionHandler you wrap each submitted runnable into a runnable of your own which executes (calls run) the real runnable inside a try-catch-block.

EDIT
As pointed out by Mark, it's important to wrap the Runnable passed to ScheduledExecutorService instead of the one passed to the ThreadFactory.

执笔绘流年 2024-10-04 01:02:09

警告:此方法不适用于预定线程池执行器。由于与其他线程池执行器的相关性,该答案已被取消删除。请参阅威利的回答

重写 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;
    }
}

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

Override the ThreadFactory to give Threads an 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;
    }
}
无语# 2024-10-04 01:02:09

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

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

自找没趣 2024-10-04 01:02:09

您还可以使用 “nofollow">Spring 框架,它公开了一个方法来设置错误处理程序并为您完成所有包装。默认行为取决于任务类型:

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

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

TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask)

TaskScheduler 在内部使用的内容。

You could also use a ThreadPoolTaskScheduler from 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:

If the provided ErrorHandler is 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.

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

TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask)

which the TaskScheduler uses internally.

灼疼热情 2024-10-04 01:02:09

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

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

记忆之渊 2024-10-04 01:02:09

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

Consider adding a static event in your ScheduledThreadPoolExecutor class 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文