java - 当 run 方法抛出 NPE 时,ScheduledExecutorService 不打印异常堆栈跟踪

标签 java scheduled-tasks java.util.concurrent

在下面给出的代码中,i.intValue 抛出NPE。但它没有被打印出来。相反,ScheduledExecutorService 通过取消后续执行来静默终止。 为什么?

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.*;
class Concurr
{
    public static void main(String[] args) 
    {
        ScheduledExecutorService sce = Executors.newScheduledThreadPool(1);
        Runnable task = new Runnable()
        {
            public void run()
            {
                System.out.print(".");
                Integer i = null;
                i.intValue();
            }
        };
        final ScheduledFuture<?> future = sce.scheduleAtFixedRate(task,0,2,TimeUnit.SECONDS);
        sce.schedule( new Runnable()
        {
            public void run()
            {
                future.cancel(true);
            }
        },10,TimeUnit.SECONDS);
    }
}

最佳答案

ExecutorService 捕获(并存储)其管理的 RunnableCallable 实例中引发的所有异常。

ScheduledFuture 有一个 get() 方法,如果在执行 期间抛出异常,该方法会抛出包含异常的 ExecutionException可运行。如果执行被取消,它会抛出 CancellationException

System.out.println(future.get()); // returns null otherwise 

main的末尾。您将得到以下输出:

.Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NullPointerException
    at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)
    at java.util.concurrent.FutureTask.get(Unknown Source)
    at test.Main.main(Main.java:50)
Caused by: java.lang.NullPointerException
    at test.Main$1.run(Main.java:38)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

如果您的异步任务应该返回一个值,您可以使用 Callable 而不是 Runnable 并将其传递给 ExecutorService。您可以使用 future.get() 获取该值。

每次调用 future.get() 都会返回 Runnable 的一次执行结果。例如,您已安排任务每 5 秒运行一次。如果 16 秒后,您调用

future.get();
future.get();
future.get();
future.get();

该代码将在第四次调用时阻塞,因为所有其他调用都已完成并将返回结果(除非其中一个调用失败)。

关于java - 当 run 方法抛出 NPE 时,ScheduledExecutorService 不打印异常堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18217467/

相关文章:

java - 停止当前线程并等待 HTTP 连接

java - 一个常规的 ConfigObject 的 pretty-print ?

ASP.NET MVC3如何使用间隔一小时的计时器执行 Controller 的操作方法

java - 通过java在特定日期发送自动邮件

java - Semaphore.acquire() 会因虚假唤醒而抛出 InterruptedException 吗?

Java 锁定数组范围

java - hibernate 。保留对最后一个 child 的引用

java - 我无法理解 java.sql.date 的文档

c - 在 Linux 内核中启用调度程序统计信息

java - ThreadPoolTask​​Executor 抛出 RejectedExecutionException