Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当回调捕获InterruptedException时,Future.get挂起_Java - Fatal编程技术网

Java 当回调捕获InterruptedException时,Future.get挂起

Java 当回调捕获InterruptedException时,Future.get挂起,java,Java,此代码挂起。我知道我为未执行的future调用future.get(),但我希望在future.get()方法上看到CancellationException或InterruptedException或其他一些异常。我错了吗 public class ExecutorTest { static ExecutorService executorService = Executors.newFixedThreadPool(1); public static void main(Str

此代码挂起。我知道我为未执行的future调用future.get(),但我希望在future.get()方法上看到CancellationException或InterruptedException或其他一些异常。我错了吗

public class ExecutorTest {
    static ExecutorService executorService = Executors.newFixedThreadPool(1);
    public static void main(String[] args) throws Exception {
        List<Future> futures = new ArrayList<Future>();
        for (int i = 0; i < 10; i++) {
            Future<Object> future = executorService.submit(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    System.out.println("Start task");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Finish task");
                    return "anything";
                }
            });
            futures.add(future);
        }

        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                    System.out.println("Shutdown Now");
                    executorService.shutdownNow();
                } catch (InterruptedException e) {
                    System.out.println("Interrupted Exception during shutdown");
                }
            }
        }.start();

        for(Future f : futures) {
            System.out.println("-------------------------");
            System.out.println("before sleep");
            Thread.sleep(3000);
            System.out.println("after sleep...");
            try {
                f.get();
            } catch (Exception ex) {
                System.out.println("exception during future.get");
            }
            System.out.println("after get!");
        }

    }
}
Java8,Intellij

如果我替换

System.out.println("Start task");
try {
    Thread.sleep(3000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
用这个

System.out.println("Start task");
Thread.sleep(3000);
那它就挂不住了


我很沮丧…

当您调用
shutdownow
时,
ExecutorService
会删除任何已计划但尚未运行的任务,并将它们作为
列表返回给您。这些任务有一个对应的
未来
,您已经对其进行了引用。由于这些任务从未运行过,因此它们从未产生结果,即从未完成。因此,这些任务的
未来#get()
将永远不会返回

如果愿意,可以返回并运行这些任务

executorService.shutdownNow().forEach(r -> r.run());
您将看到所有
Future#get()
调用返回


如果知道任务已完成/取消,则可能只应调用
Future#get()
。或者,给它一个超时。

当您调用
shutdownow
时,
ExecutorService
将删除任何已计划但尚未运行的任务,并将它们作为
列表返回给您。这些任务有一个对应的
未来
,您已经对其进行了引用。由于这些任务从未运行过,因此它们从未产生结果,即从未完成。因此,这些任务的
未来#get()
将永远不会返回

如果愿意,可以返回并运行这些任务

executorService.shutdownNow().forEach(r -> r.run());
您将看到所有
Future#get()
调用返回

如果知道任务已完成/取消,则可能只应调用
Future#get()
。或者,给它一个超时。

当线程1调用FutureTask#get时,则调用线程1#wait。现在要继续线程1,应该有人通知它。仅当FutureTask终止时(在FutureTask#set、FutureTask#setException或FutureTask#cancel上)才会调用通知。但是在我的例子中,FutureTask从来没有启动过,因为现在关机了(FutureTask处于新状态)。因此,它从未被终止,线程1#notify也从未被调用。 为了解决这个问题,我从“立即关闭”开始就没有启动期货,也没有给FutureTask打电话

PS:老实说,FutureTask使用sun.misc.Unsafe#park#unpark方法而不是wait和notify。

当线程1调用FutureTask#get时,线程1#wait被调用。现在要继续线程1,应该有人通知它。仅当FutureTask终止时(在FutureTask#set、FutureTask#setException或FutureTask#cancel上)才会调用通知。但是在我的例子中,FutureTask从来没有启动过,因为现在关机了(FutureTask处于新状态)。因此,它从未被终止,线程1#notify也从未被调用。 为了解决这个问题,我从“立即关闭”开始就没有启动期货,也没有给FutureTask打电话


PS:老实说,FutureTask使用sun.misc.Unsafe#park#unpark方法,而不是等待和通知。

挂起是什么意思?在那之后应该执行什么?所谓挂起,我的意思是,如果我启动代码,它不会终止,也不会打印'after get!'你说的绞死是什么意思?在那之后应该执行什么?所谓挂起,我的意思是,如果我启动代码,它不会终止,也不会打印'after get!'你的意思是,在将来调用从未执行过的get()方法是绝对错误的吗?为什么文档中没有关于它的内容,并且存在诸如Cancellationexception之类的异常?只有当我捕捉到Interruptedexception时,它才会挂起。@EugeneTo它不仅仅在捕捉到异常时挂起。它在任何情况下都会挂起。整个异常结果在@chiastic security now deleted答案中进行了解释。这与
关闭后程序挂起的原因无关。调用
get()
没有错。如果您不确定是否会得到结果,就不应该调用它。如果您使用的是标准ThreadPoolExecutor,则返回的Runnable与submit返回的Futures相同(至少从Java 7开始)。如果您将它们转换为Futures,那么您可以调用
Future#cancel(true)
。然后,您稍后的
get()
调用将抛出一个
CancellationException
。您的意思是,将来调用从未执行过的get()方法是绝对错误的吗?为什么文档中没有关于它的内容,并且存在诸如Cancellationexception之类的异常?只有当我捕捉到Interruptedexception时,它才会挂起。@EugeneTo它不仅仅在捕捉到异常时挂起。它在任何情况下都会挂起。整个异常结果在@chiastic security now deleted答案中进行了解释。这与
关闭后程序挂起的原因无关。调用
get()
没有错。如果您不确定是否会得到结果,就不应该调用它。如果您使用的是标准ThreadPoolExecutor,则返回的Runnable与submit返回的Futures相同(至少从Java 7开始)。如果您将它们转换为Futures,那么您可以调用
Future#cancel(true)
。然后,您稍后的
get()
调用将抛出一个
CancellationException
,正如您所期望的那样。