我有一个Controller
类和一个Monitor
工作线程。
控制器线程看起来像这样
public class ControllerA {
public void ControllerA(){
try{
doWork();
}
catch(OhNoException e){
//catch exception
}
public void doWork() throws OhNoException{
new Thread(new Runnable(){
public void run(){
//Needs to monitor resources of ControllerA,
//if things go wrong, it needs to throw OhNoException for its parent
}
}).start();
//do work here
}
}
这种设置是否可行?如何将异常抛出到线程的外部?
答案 0 :(得分:7)
如何将异常抛出到线程外部?
你可以通过几种方式做到这一点。您可以在主题上设置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;
}
}
答案 1 :(得分:1)
Runnable接口不能抛出已检查的异常或返回值。在Callable接口中,您可以调用任何返回值或抛出异常的worker方法。监视器的主要任务是
使用可调用实例声明和初始化未来。
一个getResult()方法,它可以有一个return future.get();
语句,并且应该在其throws子句中声明任何已检查的异常,以便它由调用代码处理。这样我们就不必返回null。