java - 当 ScheduledExecutorService 的任务抛出异常时,不会打印堆栈跟踪

标签 java dropwizard

我正在通过 Dropwizard 的 LifecycleEnvironment.scheduledExecutorService() 创建 ScheduledExecutorService。我在上面安排了四个任务,这些任务在 3 秒后抛出异常。问题是没有打印异常的堆栈跟踪,因此我无法跟踪它发生的原因。抛出异常一的任务永远不会重新启动。

我尝试设置默认的未捕获异常处理程序,但它也没有帮助:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable throwable) {
                System.err.println("An exception occurred as below:");
                throwable.printStackTrace(System.err);
            }
        });

完整代码如下:

这是扩展应用程序的主要驱动类:

应用程序.java

import io.dropwizard.Application;
import io.dropwizard.setup.Environment;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class App extends Application<AppConfiguration> {

    public void run(AppConfiguration appConfiguration, Environment environment) throws Exception {
        final ScheduledExecutorService scheduledExecutorService = environment.lifecycle()
                .scheduledExecutorService("throwing-exception-threads").threads(4)
                .build();

        scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);

        final HelloWorldResource resource = new HelloWorldResource();
        environment.jersey().register(resource);
    }

    public static void main(String[] args) throws Exception {
        new App().run(args);
    }
}

按固定时间间隔安排任务的代码如下。它打印每秒递增的计数器值。当计数器为 3 时,它会抛出 NullPointerException。

ThreadToDie.java

public class ThreadToDie implements Runnable {

    int i = 0;

    @Override
    public void run() {
        i++;
        System.out.printf("Value of i: %d\n", i);
        if (i % 3 == 0) {
            System.out.printf("Throwing NullPointerException\n");
            throw new NullPointerException("This should be printed.");
        }
    }
}

为了完整起见,以下是配置类和 HelloWorld API 类。尽管在问题中询问它们包含的内容并不相关。

AppConfiguration.java

import io.dropwizard.Configuration;

public class AppConfiguration extends Configuration {
}

HelloWorldResource.java

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Optional;

@Path("/hello")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {

    @GET
    public String hello(@QueryParam("name") Optional<String> name) {
        final String retVal = String.format("Hello %s!", name.orElse("World"));
        return retVal;
    }
}

最佳答案

参见Why is UncaughtExceptionHandler not called by ExecutorService?了解为什么 UncaughtExceptionHandler 永远不会被触发 - 您提供的每个任务都由捕获所有异常的工作线程处理。

当您向执行者提交任务时,您会收到 Future 并可以通过这种方式访问​​异常:

ScheduledFuture<?> future = scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
try {
   future.get();
} catch (ExecutionException ex) {
   ex.getCause().printStackTrace();
}

Future.get 将等待任务完成或出错。

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

相关文章:

java - 使用 JavaFX 的 Jasper 报告

java - Android ListView 中的阿拉伯文字

java - 测试运行完成后,DropwizardServiceRule 抛出 NullPointerException

timeout - Dropwizard logback 异步日志轮换导致应用程序线程等待

java - 如何使用 BindBeans 将字符串列表输入到 SQL

groovy - 仅在特定子项目上运行 Gradle ShadowJar 插件

java - GWT:使用 JSON 服务

java - 如何在 Apache Spark 中执行简单的reduceByKey?

java - 反序列化许多子节点以添加对对象的引用 xStream java

java - dropwizard hibernate 使用服务器内部的资源