我正在開發一個多線程項目,其中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