我正在开发一个多线程项目,其中Thread
可能会抛出Error
(而不是Exception
)。没有找到任何关于多线程中如何处理错误的可靠信息,我决定做一些测试并发现结果可能不一致。Java如何处理多线程中的错误?
这是我的测试代码,以及评论结果。
public class MultiThreadError {
public static class ErrorThrowingRunnable implements Runnable{
private final boolean throwsError;
public ErrorThrowingRunnable(boolean throwsError){
this.throwsError = throwsError;
}
@Override
public void run() {
try {
// Wait between .5 and 1.5 seconds
Thread.sleep(500 + new Random().nextInt(1000));
} catch (InterruptedException ex) {}
if(throwsError){
throw new Error(Thread.currentThread().getName());
}else{
System.out.println(Thread.currentThread().getName());
}
}
}
public static void regularThreadPool(){
// Crashes individual thread; swallows error
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(true));
threadPool.shutdown();
}
public static void onDemandThreads(){
// Crashes individual thread; displays error
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(true)).start();
}
public static void onDemandThreadPool(){
// Same as onDemandThreads()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(true));
threadPool.shutdown();
}
public static void tooSmallThreadPool(){
// When an error is thrown, apparently the thread that threw
// the error is not reused, reducing the pool size
ExecutorService threadPool = Executors.newFixedThreadPool(3);
threadPool.execute(new ErrorThrowingRunnable(true));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.shutdown();
}
}
看起来好像结果应该是我的预期:抛出错误的线程终止,显示消息。事实证明,当一个Runnable
传递给ExecutorService
使用submit(Runnable)
时,它被封装在RunnableFuture<Void>
不处理错误,我找不到方法来改变这种行为,而不是直接调用execute(Runnable)
,由于某种原因doesn没有表现出相同的行为。
对此有没有“最佳实践”?如果我知道一个线程可能会抛出一个错误,是否有一种方法来submit
它到一个ExecutorService而不是吞下该错误?
在小样式的笔记中,您应该避免抛出错误。它们表明严重的问题,您不应该尝试处理(例如内存不足)。如果你想从'Runnable'中抛出一些东西,你应该使用'RuntimeException'(或其子类)。 –
[处理来自Java ExecutorService任务的异常]可能的重复(http://stackoverflow.com/questions/2248131/handling-exceptions-from-java-executorservice-tasks) –
只是为了确保,'RunnableFuture'_handlers_错误正好。所有可运行的调用都被封装在try/finally中。你的意思是说你看不到我怀疑的错误信息。 – Gray