对 Future.get() 块的方法调用.这真的是可取的吗? [英] Method call to Future.get() blocks. Is that really desirable?

查看:49
本文介绍了对 Future.get() 块的方法调用.这真的是可取的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将其标记为重复之前,请仔细阅读问题.

Please read the question carefully before marking this as duplicate.

下面是伪代码的片段.我的问题是 - 下面的代码不会破坏并行异步处理的概念吗?

Below is the snippet of the pseudo code. My question is- Does the below code not defeat the very notion of parallel asynchronous processing?

我问这个的原因是因为在下面的代码中,主线程将提交一个要在不同线程中执行的任务.在队列中提交任务后,它会阻塞 Future.get() 方法让任务返回值.我宁愿让任务在主线程中执行,而不是提交到不同的线程并等待结果.通过在新线程中执行任务,我获得了什么?

The reason I ask this is because in the below code the main thread would submit a task to be executed in a different thread. After submitting the task in the queue, it blocks on Future.get() method for the task to return the value. I would rather have the task executed in the main thread rather than submitting to a different thread and waiting for the results. What is that I gained by executing the task in a new thread?

我知道你可以等待有限的时间等,但如果我真的关心结果呢?如果要执行多个任务,问题会变得更糟.在我看来,我们只是在同步进行工作.我知道提供非阻塞侦听器接口的 Guava 库.但我很想知道我的理解对 Future.get() API 是否正确.如果是正确的,为什么Future.get() 被设计成阻塞从而打败了整个并行处理过程?

I am aware that you could wait for a limited time etc, but then what if I really care about the result? The problem gets worse if there are multiple tasks to be executed. It seems to me that we are just doing the work synchronously. I am aware of the Guava library which provides a non blocking listener interface. But I am interested to know if my understanding is correct for the Future.get() API. If it is correct, why is the Future.get() designed to block thereby defeating the whole process of parallel processing?

注意 - 为了记录,我使用 JAVA 6

Note - For the record, I use JAVA 6

public static void main(String[] args){

private ExectorService executorService = ...

Future future = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Asynchronous Callable");
        return "Callable Result";
    }
});

System.out.println("future.get() = " + future.get());
}

推荐答案

Future 为您提供方法 isDone() ,它不会阻塞并在计算完成时返回 true,否则为假.

Future offers you method isDone() which is not blocking and returns true if computation has completed, false otherwise.

Future.get() 用于获取计算结果.

您有几个选择:

  • 调用 isDone() 并且如果结果准备好通过调用 get() 请求它,注意没有阻塞
  • 使用 get()
  • 无限期地阻塞
  • 使用 get(long timeout, TimeUnit unit)
  • 阻止指定的超时时间
  • call isDone() and if the result is ready ask for it by invoking get(), notice how there is no blocking
  • block indefinitely with get()
  • block for specified timeout with get(long timeout, TimeUnit unit)

Future API 的全部内容就是从执行并行任务的线程中获取值的简单方法.如果您愿意,这可以同步或异步完成,如上面的项目符号所述.

The whole Future API thing is there to have easy way obtaining values from threads executing parallel tasks. This can be done synchronously or asynchronously if you prefer, as described in bullets above.

使用缓存更新示例

这是 Java Concurrency In Practice 中的缓存实现,是 Future 的绝佳用例.

Here is a cache implementation from Java Concurrency In Practice, an excellent use case for Future.

  • 如果计算已经在运行,对计算结果感兴趣的调用者将等待计算完成
  • 如果结果在缓存中准备好,调用者将收集它
  • 如果结果还没有准备好并且计算还没有开始,调用者将开始计算并将结果包装在Future中供其他调用者使用.
  • If the computation is already running, caller interested in result of computation will wait for computation to finish
  • If the result is ready in the cache, caller will collect it
  • if the result is not ready and computation has not started yet, caller will start computation and wrap result in Future for other callers.

这一切都可以通过 Future API 轻松实现.

This is all easily achieved with Future API.

package net.jcip.examples;

import java.util.concurrent.*;
/**
 * Memoizer
 * <p/>
 * Final implementation of Memoizer
 *
 * @author Brian Goetz and Tim Peierls
 */
public class Memoizer <A, V> implements Computable<A, V> {
    private final ConcurrentMap<A, Future<V>> cache
            = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

public Memoizer(Computable<A, V> c) {
    this.c = c;
}

public V compute(final A arg) throws InterruptedException {
    while (true) {

        Future<V> f = cache.get(arg);
        // computation not started
        if (f == null) {
            Callable<V> eval = new Callable<V>() {
                public V call() throws InterruptedException {
                    return c.compute(arg);
                }
            };

            FutureTask<V> ft = new FutureTask<V>(eval);
            f = cache.putIfAbsent(arg, ft);
            // start computation if it's not started in the meantime
            if (f == null) {
                f = ft;
                ft.run();
            }
        }

        // get result if ready, otherwise block and wait
        try {
            return f.get();
        } catch (CancellationException e) {
            cache.remove(arg, f);
        } catch (ExecutionException e) {
            throw LaunderThrowable.launderThrowable(e.getCause());
        }
    }
  }
}

这篇关于对 Future.get() 块的方法调用.这真的是可取的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆