如何向線程外部拋出異常?
你可以做到這一點的幾種方法。您可以在線程上設置UncaughtExceptionHandler
,或者您可以使用ExecutorService.submit(Callable)
並使用從Future.get()
獲得的例外。
最簡單的方法是使用ExecutorService
:
ExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
Future<Void> future = threadPool.submit(new Callable<Void>() {
public Void call() throws Exception {
// can throw OhNoException here
return null;
}
});
// you need to shut down the pool after submitting the last task
threadPool.shutdown();
// this can throw ExecutionException
try {
// this waits for your background task to finish, it throws if the task threw
future.get();
} catch (ExecutionException e) {
// this is the exception thrown by the call() which could be a OhNoException
Throwable cause = e.getCause();
if (cause instanceof OhNoException) {
throw (OhNoException)cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
}
}
如果你想使用UncaughtExceptionHandler
那麼你可以這樣做:
Thread thread = new Thread(...);
final AtomicReference throwableReference = new AtomicReference<Throwable>();
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
throwableReference.set(e);
}
});
thread.start();
thread.join();
Throwable throwable = throwableReference.get();
if (throwable != null) {
if (throwable instanceof OhNoException) {
throw (OhNoException)throwable;
} else if (throwable instanceof RuntimeException) {
throw (RuntimeException)throwable;
}
}
哇之前從未見過這樣的事情。我想知道Future線程會不會在後臺運行,還是隻運行一次並關閉?它何時開始? – Bonk
未來線程在提交時立即開始。它在後臺運行一次,然後在'call()'方法返回@Yonk時停止。 – Gray
爲什麼你需要第二個例子中的AtomicReference,在thread.join上沒有內存障礙(請參閱http://gee.cs.oswego.edu/dl/cpj/jmm.html)?所以所有的寫入都應該是可見的 – leozilla