为什么我们在这个例子中看不到堆栈跟踪?
public class NoStackTraceTester implements Runnable {
private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> lifeCheckFuture;
@Override
public void run() {
lifeCheckFuture = startLifecheck();
}
private ScheduledFuture<?> startLifecheck()
{
Runnable lifeCheck = new Runnable()
{
@Override
public void run()
{
System.out.println("sending lifecheck ...");
throw new RuntimeException("bang!");
}
};
return scheduler.scheduleAtFixedRate(lifeCheck, 1000, 1000, TimeUnit.MILLISECONDS);
}
public static void main(String[] args) {
new NoStackTraceTester().run();
}
}
如果您尝试对异常进行注释,那么您将执行lifecheck函数的重复任务。 但是如果抛出异常,则线程停止但没有细节:(
你知道为什么吗?
答案 0 :(得分:3)
ExecutorService将任何捕获的Throwable放置在Future对象中。如果你检查这个,你可以看到抛出了什么异常。这并不总是令人满意的,因此您可能必须在run()方法中捕获并处理或记录任何异常。
注意:一旦异常逃脱,任务不会再次重复。
Runnable lifeCheck = new Runnable() {
@Override
public void run() {
try {
System.out.println("sending lifecheck ...");
throw new RuntimeException("bang!");
} catch(Throwable t) {
// handle or log Throwable
}
}
};
答案 1 :(得分:1)
如果您需要异常报告,则必须自行插入处理代码。 ExecutorService不会自动将异常跟踪发送到标准输出,并且它不是很好,因为这很少是生产代码中我们需要的。
基本上,这就是方法:
public void run()
{
try {
System.out.println("sending lifecheck ...");
throw new RuntimeException("bang!");
} catch (Throwable t) { t.printStackTrace(); }
}
答案 2 :(得分:0)
ThreadPoolExecutor中的afterExecute()方法可以被覆盖:
class MyThreadPoolExecutor extends ThreadPoolExecutor {
public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// If submit() method is called instead of execute()
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException e) {
t = e;
} catch (ExecutionException e) {
t = e.getCause();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
if (t != null) {
// Exception occurred
System.err.println("Uncaught exception is detected! " + t
+ " st: " + Arrays.toString(t.getStackTrace()));
}
// ... Perform cleanup actions
}
}
final class MyTask implements Runnable {
@Override public void run() {
System.out.println("My task is started running...");
// ...
throw new ArithmeticException(); // uncatched exception
// ...
}
}
public class ThreadPoolExecutorHandler {
public static void main(String[] args) {
// Create a fixed thread pool executor
ExecutorService threadPool = new MyThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>());
threadPool.execute(new MyTask());
// ...
}
}
源:https://medium.com/@aozturk/how-to-handle-uncaught-exceptions-in-java-abf819347906(请注意,我修改了此处发布的代码,使其不再执行,因为该问题仅要求进行堆栈跟踪打印)