有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java执行器服务。调用所有(超时,时间单位)与未来。获取(超时,时间单位)

我正在使用执行器服务。invokeAll(可调用、超时、时间单位)方法

在提交给ExecutorService的每个可调用服务中,我都有一个未来。get()

将成为未来。即使executorService已超时,get()仍将在后台运行

我是否必须指定未来的超时。获取(timeout,TimeUnit)并抛出一个TimeoutException,以确保未来被终止


共 (2) 个答案

  1. # 1 楼答案

    正如the documentation所述:

    Upon return, tasks that have not completed are cancelled.

    它没有明确说明,但它使用Future.cancel(true),即中断正在运行的任务。由于Future.get()支持中断,这将导致它通过抛出InterruptedException来完成。如果Callable没有捕捉到它,也没有执行任何可能重置中断状态的操作,这意味着如果指定给invokeAll的超时时间已过,可调用项将停止在Future.get()中等待

    然而,invokeAll只取消未来,因此,发送中断信号,但不等待线程对其做出反应并完成Callable代码的执行。因此,当invokeAll由于超时而完成时,一些线程可能仍然在已经取消的任务上运行。但是,如果这些任务仅仅由future::get组成,那么这就不应该是一个问题


    但是,如果您只想等待现有Future列表的完成,那么您可以更高效地完成这项工作。毕竟,您正在将每个Future包装成一个调用Future.getCallable,该invokeAll将包装成另一个Future,可能会在每个未来阻塞一个工作线程,然后等待所有这些未来的完成。最后一步正是这项任务的目的,所以你可以不用前面的步骤来完成它,例如:

    public static void waitForAll(Collection<? extends Future<?>> futures,
                                  long timeout, TimeUnit unit)
        throws InterruptedException {
    
        long nanos = unit.toNanos(timeout);
        boolean done = false;
        try {
            final long deadline = System.nanoTime() + nanos;
            final int size = futures.size();
            for(Future<?> f: futures) {
                if(!f.isDone()) {
                    if (nanos <= 0L) return;
                    try { f.get(nanos, TimeUnit.NANOSECONDS); }
                    catch(CancellationException | ExecutionException ignore) {}
                    catch(TimeoutException toe) { return; }
                    nanos = deadline - System.nanoTime();
                }
            }
            done = true;
        }
        finally { if (!done) for(Future<?> f: futures) f.cancel(true); }
    }
    

    这基本上就是AbstractExecutorService在提交了所有Callable之后等待所有期货完成的方式,为每个期货创建一个Future。如前所述,如果你想做的只是等待现有未来的列表,你可以直接这样做,而不需要通过向执行者提交作业来浪费资源。使用这种方法的另一个好处是,这将取消原始的期货,而不仅仅是取消等待期货的工作。您还可以依赖此方法中断取消,而此属性不是为invokeAll显式指定的

  2. # 2 楼答案

    来自Javadoc

    Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires

    所以1。所有结果都将由所有Callable提供,包括内部future.get()调用的结果,以及2。一旦invokeAll返回(即在超时之前),所有期货都将终止