简体   繁体   中英

No stack trace is printed when ScheduledExecutorService's task throws an exception

I am creating a ScheduledExecutorService through Dropwizard's LifecycleEnvironment.scheduledExecutorService() . I schedule four tasks on it, which throw an exception after 3 seconds. The problem is that no stack trace is printed for exceptions and hence I cannot trace why it happened. The task which throws exception one is never restarted.

I tried setting a default uncaught exception handler but it didn't help either:

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

Following is the complete code:

This is the main driving class which extends Application:

App.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);
    }
}

Code for task being scheduled at fixed interval is below. It prints counter value which is incremented at each second. When the counter is 3 it throws a 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.");
        }
    }
}

For the sake of completeness following are the Configuration class and A HelloWorld API class. Though in the question asked what they contain is not relevant.

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

See Why is UncaughtExceptionHandler not called by ExecutorService? for an explanation on why the UncaughtExceptionHandler is never triggered - each task you supply is handled by a worker that catches all exceptions.

When you submit a task to an executor you receive back a Future and can access the exception in that way:

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

Future.get will wait until the task has completed or errored.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM