2

Callable が future.get(timeout, TimeUnit.SECONDS) によってキャンセルされた場合、スレッド内の 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);

最終的に常に呼び出されることは承知していますが、スレッドがどのように中断されるかについて何かが欠けていると思います。これは私が実行したテストで、finally ブロックが起動されたことを示していません。

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

1 に答える 1

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ブロックに入ると、何らかのJVMの障害とクラッシュがない限り、ブロックは常に呼び出されます(割り込みの有無にかかわらずfinallyスレッドがまったく中断されていないのではないかと思うので、実行を続けます。

于 2013-01-15T14:46:15.460 に答える