程序永远不会在 java 中的 TimeoutException 上结束
Program never ends on TimeoutException in java
我正在尝试一个 java 程序来理解 Future
的工作原理。
我写了下面的程序,它永远不会结束。如果我在 Thread.sleep()
中输入一个小于 10 的值,那么它有效但不适用于值 >=10
.
我知道导致问题的部分可能是 future.get 调用。
然而,经过进一步分析,我尝试的是处理所有异常,而不是让 jvm 处理它们。
例如:
现在它正常终止了。
我做了进一步的检查,发现如果我抛出 ExecutionException
和 InterruptedException
并处理 TimeoutException
它再次正常工作。
这里奇怪的部分是我必须强制处理 TimeoutException,否则它不会工作。我不太确定为什么这种奇怪的行为会持续存在。
我正在使用 OpenJDK 15。
如果有人想在这里尝试代码片段:
import java.util.concurrent.*;
public class FixedThreadPoolExecutorDemo2 {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
workWithFutureCallable(executorService);
executorService.shutdownNow();
}
private static void workWithFutureCallable(ExecutorService executorService) throws ExecutionException, InterruptedException, TimeoutException {
Future<Integer> myOtherFuture = executorService.submit(() -> {
try {
Thread.sleep(109);
} catch (InterruptedException e) {
}
return 1000;
});
System.out.println("myOtherFuture should be cancelled if running for more than specified time. ->" + myOtherFuture.get(10, TimeUnit.MILLISECONDS));
}
}
TimeoutException
未在 main
中捕获,因此 main
也在没有 调用 shutdownNow
的情况下突然终止 。主线程已终止,但 Executors
创建的线程默认为非守护进程,因此虚拟机未关闭,Executors
个线程继续 运行.
解决方案:
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
workWithFutureCallable(executorService);
} finally {
executorService.shutdownNow();
}
}
或
实施 ThreadFactory
来创建守护线程并使用它来获取服务:
ExecutorService executorService = Executors.newFixedThreadPool(2, r -> {
var thread = new Thread(r);
thread.setDaemon(true);
return thread;
});
甚至更好,至少在生产代码中,捕获并处理 Exception
s(连同 finally
块。)
我正在尝试一个 java 程序来理解 Future
的工作原理。
我写了下面的程序,它永远不会结束。如果我在 Thread.sleep()
中输入一个小于 10 的值,那么它有效但不适用于值 >=10
.
我知道导致问题的部分可能是 future.get 调用。
然而,经过进一步分析,我尝试的是处理所有异常,而不是让 jvm 处理它们。
例如:
现在它正常终止了。
我做了进一步的检查,发现如果我抛出 ExecutionException
和 InterruptedException
并处理 TimeoutException
它再次正常工作。
这里奇怪的部分是我必须强制处理 TimeoutException,否则它不会工作。我不太确定为什么这种奇怪的行为会持续存在。
我正在使用 OpenJDK 15。
如果有人想在这里尝试代码片段:
import java.util.concurrent.*;
public class FixedThreadPoolExecutorDemo2 {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
workWithFutureCallable(executorService);
executorService.shutdownNow();
}
private static void workWithFutureCallable(ExecutorService executorService) throws ExecutionException, InterruptedException, TimeoutException {
Future<Integer> myOtherFuture = executorService.submit(() -> {
try {
Thread.sleep(109);
} catch (InterruptedException e) {
}
return 1000;
});
System.out.println("myOtherFuture should be cancelled if running for more than specified time. ->" + myOtherFuture.get(10, TimeUnit.MILLISECONDS));
}
}
TimeoutException
未在 main
中捕获,因此 main
也在没有 调用 shutdownNow
的情况下突然终止 。主线程已终止,但 Executors
创建的线程默认为非守护进程,因此虚拟机未关闭,Executors
个线程继续 运行.
解决方案:
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
workWithFutureCallable(executorService);
} finally {
executorService.shutdownNow();
}
}
或
实施 ThreadFactory
来创建守护线程并使用它来获取服务:
ExecutorService executorService = Executors.newFixedThreadPool(2, r -> {
var thread = new Thread(r);
thread.setDaemon(true);
return thread;
});
甚至更好,至少在生产代码中,捕获并处理 Exception
s(连同 finally
块。)