2016-10-11 164 views
0

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

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

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

下面是完整的代码:

这是一个扩展应用的主要驱动类:

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

任务代码按固定间隔计划在下面。它打印每秒递增的计数器值。当计数器是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."); 
     } 
    } 
} 

为了完整以下起见是Configuration类和一个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; 
    } 
} 

回答

1

关于为什么UncaughtExceptionHandler永远不会触发的说明,请参见Why is UncaughtExceptionHandler not called by ExecutorService? - 每次你提供任务由捕获所有异常工人处理。

当您提交任务执行人收到回Future,并且可以以这种方式访问​​异常:

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

Future.get会等到任务完成或出错。

+0

谢谢,这很清楚,直接:) – Xolve