期货,TimeoutException和带有finally块的Callables

时间:2013-01-15 14:36:09

标签: java concurrency future callable timeoutexception

如果通过future.get(timeout,TimeUnit.SECONDS)取消Callable,是否会调用带有线程的finally块?

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!");
        }
    }

}

看起来如果我添加awaitTermination它运行。 这个测试通过......

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();
    }
}

1 个答案:

答案 0 :(得分: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故障和崩溃。我怀疑你的线程没有被中断,所以只是继续运行。