我想實現異步執行的可調用一個泛型類,但我不知道的語義。春@Async與未來可贖回
@Component
public class MyCallerImpl implements MyCaller {
@Async
@Override
public <T> Future<T> runAsync(Callable<T> callable) throws Exception {
return new AsyncResult<T>(callable.call());
}
}
基本上,該組件使用@Async註釋異步執行任意可調用的任意操作。
我不確定在拋出方法簽名的條款除外。
JUnit測試:
@ContextConfiguration("classpath:test-config.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class RunnerTest{
@Resource(name="myCallerImpl")
private MyCaller myCaller;
@Test
public void testException(){
final Callable<String> callable = new Callable<String>(){
@Override
public String call() throws Exception{
throw new MyException("foobar");
}
};
try
{
final Future<String> future = myCaller.runAsync(callable); // this can throw Exception due to Callable.call()
future.get(); // this can throw InterruptedException and ExecutionException
}
catch (final InterruptedException ie)
{
// do someting
}
catch (final ExecutionException ee)
{
// we want to check the cause
final Throwable cause = ee.getCause();
assertTrue(cause instanceof MyException);
}
catch (final Exception e)
{
// Not sure what to do here.
// Must be caught as it is declared to
// be thrown from the MyCaller.runAsync() method
// but nothing will really ever get here
// since the method is @Async and any exception will be
// wrapped by an ExecutionException and thrown during Future.get()
fail("this is unexpected);
}
我的問題是如何處理()在拋出MyCallerImpl.runAsync的子句中聲明的異常?
我已經宣佈的唯一原因是因爲這樣我打電話的調用。我原本在異步方法如下:
FutureTask<T> futureTask = new FutureTask<T>(callable);
futureTask.run();
return futureTask;
但是,當異常是從可調用該實例中拋出的,它就會在爲ExecutionException裹兩次,當FutureTask.run()最終被稱爲第一次FutureTask.Sync.innerRun()捕獲異常,並調用innnerSetException(),當AsyncExecutionIntercepter通過的Future.get(),最終再次檢查是否有異常,並拋出一個新的ExecutionException當包裹從未來得到結果第二次ExecutionException在innerRun中捕獲()
我也嘗試在該方法中執行以下操作:
FutureTask<T> futureTask = new FutureTask<T>(callable);
return futureTask;
我曾想過,自AsyncExecutionInterceptor調用Future.get()之後,可立即調用可調用對象,但事實並非如此。它只是掛在FutureTask.acquireSharedInterruptibly()上,並且永遠不會返回。
也許我在我頭上這裏。它的工作原理是如何使用可調用的設置,但我寧願沒有方法簽名聲明拋出異常。
有什麼建議嗎?我應該忘記這種使用可調用的異步調用的通用方法嗎?