Skip to main content
 首页 » 编程设计

java中Futures、TimeoutException 和带有finally block 的Callables

2024年09月07日7shanyou

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

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

我知道finally总会被调用,但我猜我遗漏了一些关于线程如何中断的信息。这是我运行的测试,没有显示我的finally block 被解雇。

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

请您参考如下方法:

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 block ,则 finally block 总是被调用(无论是否中断),除非出现某种 JVM 错误和崩溃。我怀疑你的线程根本没有被中断,所以只是继续运行。