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

时间:2013-08-13 19:24:50

标签: 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);
    }
}

1 个答案:

答案 0 :(得分:1)

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

ScheduledFuture有一个get()方法,如果在执行ExecutionException期间抛出一个异常,则会抛出Runnable。如果执行被取消,它会抛出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();

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