在java中,程序永远不会在TimeoutException上结束
我正在尝试一个java程序来理解未来的工作 我写了下面的程序,它永远不会结束。如果我在在java中,程序永远不会在TimeoutException上结束,java,concurrency,future,Java,Concurrency,Future,我正在尝试一个java程序来理解未来的工作 我写了下面的程序,它永远不会结束。如果我在Thread.sleep()中输入了小于10的值,那么它可以工作,但对于=10的值则不起作用 我知道造成问题的部分可能是未来。接电话 然而,在进一步的分析中,我尝试的是处理所有异常,而不是让jvm处理它们 例如: 现在一切都好了 我做了进一步的检查,发现如果我抛出ExecutionException和interruptedeexception并处理TimeoutException,它会再次正常工作。 奇怪的
Thread.sleep()
中输入了小于10的值,那么它可以工作,但对于=10的值则不起作用
我知道造成问题的部分可能是未来。接电话
然而,在进一步的分析中,我尝试的是处理所有异常,而不是让jvm处理它们
例如:
现在一切都好了
我做了进一步的检查,发现如果我抛出ExecutionException
和interruptedeexception
并处理TimeoutException
,它会再次正常工作。
奇怪的是,我必须强制处理TimeoutException,否则它将无法工作。我不太清楚为什么这种奇怪的行为会持续下去
我正在使用OpenJDK15
如果有人想尝试代码片段,请点击此处:
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));
}
}
import java.util.concurrent.*;
公共类FixedThreadPoolExecutorDemo2{
公共静态void main(字符串[]args)引发ExecutionException、InterruptedException、TimeoutException{
ExecutorService ExecutorService=Executors.newFixedThreadPool(2);
与FutureCallable合作(executorService);
executorService.shutdownNow();
}
私有静态void workWithFutureCallable(ExecutorService ExecutorService)引发ExecutionException、InterruptedException、TimeoutException{
Future myOtherFuture=executorService.submit(()->{
试一试{
睡眠(109);
}捕捉(中断异常e){
}
返回1000;
});
System.out.println(“如果运行时间超过指定时间,则应取消myOtherFuture。->”+myOtherFuture.get(10,TimeUnit.ms));
}
}
未在main
中捕获TimeoutException
,因此main
也会在未调用shutdownow
的情况下突然终止。主线程被终止,但是由执行器创建的线程默认为非守护进程,因此虚拟机不会关闭,执行器线程继续运行
解决方案:
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;
});
更好的是,至少在生产代码中,捕获并处理异常
s(以及finally
块)。当异常传递时,executor服务不会关闭,它使用的是非守护进程线程。newFixedThreadPool
的文档:“池中的线程将一直存在,直到显式关闭为止”。使用(创建)一个ThreadFactory
来创建守护进程Thread
s,或者(更好的做法是)使用try finally
始终关闭“executorService.shutdownNow();”如果您看到,则在代码中调用。您必须能够在main方法中捕获线程中断,这应该会退出应用程序。此外,我看到它进入threadgroup的uncaughtException方法,在那里它打印stacktrace并移动ahed,如果它没有看到instanceofThreadDeath
Hi@user15244370,我很抱歉,通过你的评论,我无法理解同样的事情。我添加了最后一个块,它成功了。事实上,我并不认为executorservice创建的线程是非守护进程线程。非常感谢你。另外,这里我正在研究并发性,所以是的,生产级代码将处理并发性,并且还将注意到executorservice的关闭应该只在finally块中。