在java中,程序永远不会在TimeoutException上结束

在java中,程序永远不会在TimeoutException上结束,java,concurrency,future,Java,Concurrency,Future,我正在尝试一个java程序来理解未来的工作 我写了下面的程序,它永远不会结束。如果我在Thread.sleep()中输入了小于10的值,那么它可以工作,但对于=10的值则不起作用 我知道造成问题的部分可能是未来。接电话 然而,在进一步的分析中,我尝试的是处理所有异常,而不是让jvm处理它们 例如: 现在一切都好了 我做了进一步的检查,发现如果我抛出ExecutionException和interruptedeexception并处理TimeoutException,它会再次正常工作。 奇怪的

我正在尝试一个java程序来理解未来的工作

我写了下面的程序,它永远不会结束。如果我在
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,如果它没有看到instanceof
ThreadDeath
Hi@user15244370,我很抱歉,通过你的评论,我无法理解同样的事情。我添加了最后一个块,它成功了。事实上,我并不认为executorservice创建的线程是非守护进程线程。非常感谢你。另外,这里我正在研究并发性,所以是的,生产级代码将处理并发性,并且还将注意到executorservice的关闭应该只在finally块中。