2013-01-15 26 views
1

如果通過future.get(timeout,TimeUnit.SECONDS)取消Callable,是否會調用帶線程的finally塊?Futures,TimeoutException和可變終止塊

class MyCallable implements Callable<Future<?>>{ 
    public Future<?> call(){ 
     Connection conn = pool.getConnection(); 
     try { 
      ... 
     } catch(CatchExceptions ce){ 
     } finally { 
      conn.close(); 
     } 
    } 
} 

... 

future.get(executionTimeoutSeconds, TimeUnit.SECONDS); 

我知道終於總是會被調用,但我猜我缺少一些關於線程是如何中斷的。這是我跑過的一個測試,沒有顯示我的最後一塊被解僱。

@Test 
public void testFuture(){ 
    ExecutorService pool = Executors.newFixedThreadPool(1); 
    try { 
     pool.submit(new TestCallable()).get(1, TimeUnit.SECONDS); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } catch (TimeoutException e) { 
     e.printStackTrace(); 
    } 
} 

class TestCallable implements Callable<Void> { 
    @Override 
    public Void call() throws Exception { 
     try{ 
     while(true){ 
      Thread.sleep(3000); 
      break; 
     } 
     } catch (Exception e){ 
      System.out.println("EXCEPTION CAUGHT!"); 
      throw e; 
     } finally { 
      System.out.println("FINALLY BLOCK RAN!"); 
     } 
    } 

} 

看起來像是我添加了await Termination它運行。 該測試通過...

public void testFuture(){ 
    ExecutorService pool = Executors.newFixedThreadPool(1); 
    try { 
     pool.submit(new TestCallable()).get(1, TimeUnit.SECONDS); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } catch (TimeoutException e) { 
     e.printStackTrace(); 
    } 
    try { 
     pool.awaitTermination(10, TimeUnit.SECONDS); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

回答

2

future.get(...)沒有取消線程。它只等待線程完成,如果等待超時,則拋出TimeoutException

future.cancel(true)導致線程是中斷。這可能會或可能不會阻止您的線程處理。這取決於你的try ...部分發生了什麼。例如,Thread.sleep(...),Object.wait(...)和其他方法在線程中斷時拋出InterruptedException。否則,你需要

if (Thread.currentThread().isInterrupted()) { 
    // maybe stop the thread or whatever you want 
    return; 
} 

如果輸入了try塊檢查線程中斷標誌,該finally總是調用(中斷與否),除非有某種JVM故障和系統崩潰。我懷疑你的線程沒有被中斷,所以只是繼續運行。

+1

只是有點評論:finally塊總是被調用,如果try塊開始執行。如果線程沒有進入try塊並被終止,那麼最終當然不會被調用。 – kornero

+0

好點@ kornero。我調整了我的答案。 – Gray