Java:ExecutorService和Callables:Timeout:future.get()导致程序直接中断

Java:ExecutorService和Callables:Timeout:future.get()导致程序直接中断,java,multithreading,timeout,executorservice,callable,Java,Multithreading,Timeout,Executorservice,Callable,我在Java中使用Executor服务,我注意到一个我不理解的行为。 我使用Callable,当我调用我的线程(实现Callable的类)时,我设置了一个超时。然后我用future.get()等待结果,然后我想用future.isDone()检查任务执行过程中是否出现超时 正如我在invokeAll with timeout的文档中所读到的:返回表示任务的未来列表,其顺序与迭代器为给定任务列表生成的顺序相同。如果操作未超时,则每个任务都已完成。如果超时,其中一些任务将无法完成。 所以我想,如果超

我在Java中使用Executor服务,我注意到一个我不理解的行为。 我使用Callable,当我调用我的线程(实现Callable的类)时,我设置了一个超时。然后我用
future.get()
等待结果,然后我想用
future.isDone()
检查任务执行过程中是否出现超时

正如我在invokeAll with timeout的文档中所读到的:
返回表示任务的未来列表,其顺序与迭代器为给定任务列表生成的顺序相同。如果操作未超时,则每个任务都已完成。如果超时,其中一些任务将无法完成。

所以我想,如果超时发生,或者超时没有发生,我会得到这两种情况下的未来结果列表

现在发生的情况如下:当超时发生时,代码在
future.get()
之后不会继续运行,而且我永远无法通过
future.isDone()
检查超时是否发生。我没有发现任何异常,我直接导致代码中的finally块,我真的不明白

以下是我的代码片段:

     try {
        // start all Threads
        results = pool.invokeAll(threads, 3, TimeUnit.SECONDS);

        for (Future<String> future : results)
        {
            try
            {
                // this method blocks until it receives the result, unless there is a 
                // timeout set.
                final String rs = future.get();

                if (future.isDone())
                {
                    // if future.isDone() = true, a timeout did not occur. 
                   // do something
                }
                else
                {
                    // timeout
                    // log it and do something
                    break;
                }
            }
            catch (ExecutionException e)
            {
               // log messages and break, this is a snippet!
            }
            catch (InterruptedException ex)
            {
               // log message and break, this is a snippet!
            }
        }

    }
    catch (InterruptedException ex)
    {
        // log message, this is a snippet!
    }
    finally
    {
        // when a timeout occurs, the code jumps from future.get() directly to this point!
    }
试试看{
//启动所有线程
结果=pool.invokeAll(线程,3,时间单位:秒);
用于(未来:结果)
{
尝试
{
//此方法会一直阻塞,直到收到结果为止,除非存在
//超时设置。
最后一个字符串rs=future.get();
if(future.isDone())
{
//如果future.isDone()=true,则未发生超时。
//做点什么
}
其他的
{
//超时
//记录下来,做点什么
打破
}
}
捕获(执行例外)
{
//记录消息并中断,这是一个片段!
}
捕获(中断异常例外)
{
//日志消息和中断,这是一个片段!
}
}
}
捕获(中断异常例外)
{
//日志消息,这是一个片段!
}
最后
{
//当超时发生时,代码从future.get()直接跳到这一点!
}
有人能给我解释一下,为什么我不能访问
future.isDone()
,我应该做些什么才能识别超时


谢谢大家!

我不确定您是否正确使用了
invokeAll
。javadoc说:

执行给定的任务,返回保存任务的未来列表 全部完成或超时过期时的状态和结果,以 先发生。Future.isDone()对于 返回的列表


那么调用
isDone
有什么意义呢,因为对于所有返回的期货
isDone
都是真的?

您没有捕获到
CancellationException
,这很可能是在调用
get
后抛出的。请注意,此异常扩展了RuntimeException,编译器不会警告您捕获它

阅读以下文件:

执行给定的任务,当所有任务完成或超时过期时(以先发生的为准),返回一个保留其状态和结果的未来列表。Future.isDone()对于返回列表的每个元素都为true。返回时,未完成的任务将被取消


使用已取消。如果为false,则表示没有超时。然后,如果任务没有超时,但由于任何其他原因(如空指针、断言等)出现异常,您可以调用get()并捕获executionException。如果您没有忽略异常,您可能会理解发生了什么。您如何得出我忽略它们的结论???这只是一个片段!!!我更新了我的示例。您的代码片段忽略了异常,并且您接受了一个解释抛出了CancellationException的答案,但您没有看到它。这意味着这个异常被忽略了。当然我有代码,这只是一个片段!!!我够不到挡块。我有日志消息来检查它,并对它进行了调试。您是否希望
将来出现异常。get
会引发异常?文档中说:
如果操作没有超时,每个任务都将完成。如果它确实超时,其中一些任务将无法完成。
正如我所想,Future.isDone()检查是否完成,我认为如果超时,它将返回false。看来我看错了,不可能。IDE说我的代码中从来没有抛出TimeoutException。谢谢!!!我真的不知道。现在,当我捕获这个CancellationException时,它的工作方式与预期的一样。现在我可以捕获这个超时异常,我不再需要future.isDone(),对吗?如果发生超时,它将永远不会到达这一点,如果没有超时,isDone()在任何情况下都将返回true,对吗?对。谢谢你的帮助!