2012-10-15 119 views
3

我有一個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 

    } 
} 

這樣的設置是否可行?如何向線程外部拋出異常?

回答

6

如何向線程外部拋出異常?

你可以做到這一點的幾種方法。您可以在線程上設置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; 
    } 
} 
+0

哇之前從未見過這樣的事情。我想知道Future線程會不會在後臺運行,還是隻運行一次並關閉?它何時開始? – Bonk

+1

未來線程在提交時立即開始。它在後臺運行一次,然後在'call()'方法返回@Yonk時停止。 – Gray

+1

爲什麼你需要第二個例子中的AtomicReference,在thread.join上沒有內存障礙(請參閱http://gee.cs.oswego.edu/dl/cpj/jmm.html)?所以所有的寫入都應該是可見的 – leozilla

0

Runnable接口不能拋出checked異常或返回值。在Callable接口中,您可以調用返回值或拋出異常的任何工作方法。顯示器的主要任務是

  1. 用可調用實例聲明和初始化未來。

  2. getResult()方法,該方法可以有return future.get();語句,並且應該在其throws子句中聲明任何已檢查的異常,以便由調用代碼處理它。這樣我們不必返回null。

+0

是Runnable不能僅檢查已檢查的異常RuntimeException或Errors.I只是對其進行了編輯。 – clinton

相關問題