为什么ExecutorService在invokeAny返回结果后没有关闭



当我在Java中尝试Future和Callable时,我得到了一个我目前无法理解的结果以下场景仅用于演示

根据我的理解,当Callable的集合通过invokeAny()调用提交给ExecutorService时,ExecutorService会返回它从中得到的第一个结果。检索结果后,我调用executorService.shutDown(),我希望它关闭executorService,因为它已经返回了一个结果。但是,对于以下情况,程序将停止。我也试过打executorService.shutDownNow(),但没有成功。

我尝试了同样的例子,使用了两个方法,它们分别只让线程休眠10005000秒,在第一个方法完成后,休眠executorService.shutDown()按预期工作。

我唯一的猜测是shutDown()shutDownNow()不能像cancel(mayInterruptIfRunning=true)那样中断已经在执行的线程。

有人能解释一下这里发生了什么吗?我猜对了吗?

下面是一个例子:

public class InvokeAnyExample {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
int N = 50; // If I set N = 10, program exits successfully.
ExecutorService executorService = Executors.newFixedThreadPool(2);
Callable<Long> naiveFibonacci = () -> {
log("Naive Fibonacci");
long result = fibonacciNaive(N);
log("Naive Fibonacci Finished");
return result;
};
Callable<Long> optimizedFibonacci = () -> {
log("Optimized Fibonacci");
long[] cache = new long[1000];
Arrays.fill(cache, -1);
long result = fibonacciOptimized(N, cache);
log("Optimized Fibonacci Finished");
return result;
};
Long result = executorService.invokeAny(Arrays.asList(naiveFibonacci, optimizedFibonacci), 5, TimeUnit.SECONDS);
log(String.valueOf(result));
executorService.shutdown();
//        executorService.shutdownNow();
}
private static long fibonacciNaive(int n) {
if (n == 0 || n == 1) return n;
return fibonacciNaive(n - 1) + fibonacciNaive(n - 2);
}
private static long fibonacciOptimized(int n, long[] cache) {
if (n == 0 || n == 1) return n;
if (cache[n] != -1) return cache[n];
long result = fibonacciOptimized(n - 1, cache) + fibonacciOptimized(n - 2, cache);
cache[n] = result;
return result;
}
private static void log(String message) {
String prefix = Thread.currentThread().getName();
System.out.println(String.format("In Thread (%s) : %s", prefix, message));
}
}

这是输出:

In Thread (pool-1-thread-2) : Optimized Fibonacci
In Thread (pool-1-thread-1) : Naive Fibonacci
In Thread (pool-1-thread-2) : Optimized Fibonacci Finished
In Thread (main) : 12586269025
--- PROGRAM HALTS

正如Mark Rotteveel在评论中所写:

naiveFibonacci任务不可中断。它不调用任何检查线程中断状态的方法,fibonacciNaive()方法本身也不检查线程的中断状态。

如果您想使fibonacciNaive()方法可中断,您可以将其更改为:

private static long fibonacciNaive(int n) throws InterruptedException {
if (n == 0 || n == 1) return n;
if (Thread.interrupted()) {
log("interrupt detected");
throw new InterruptedException();
}
return fibonacciNaive(n - 1) + fibonacciNaive(n - 2);
}

一旦optimizedFibonacci产生结果,naiveFibonacci任务就会停止。

更改:正如Holger所评论的,使用Thread.interrupted()比使用Thread.currentThread().isInterrupted()更可取,因为if语句中的代码将处理中断。

相关内容

  • 没有找到相关文章

最新更新