java - 对 Future.get() block 的方法调用。这真的很可取吗?

标签 java multithreading asynchronous executorservice executor

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

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

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

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

注意 - 为了记录,我使用 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,否则返回 false。

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

你有几个选择:

  • 调用isDone(),如果结果准备好通过调用get()来请求它,注意没有阻塞
  • get()
  • 无限期阻塞
  • 使用 get(long timeout, TimeUnit unit) 阻止指定超时

整个Future API 的作用在于可以轻松地从执行并行任务的线程中获取值。如果您愿意,这可以同步或异步完成,如上面的项目符号中所述。

使用缓存示例更新

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

  • 如果计算已经在运行,对计算结果感兴趣的调用者将等待计算完成
  • 如果结果在缓存中准备好,调用者将收集它
  • 如果结果尚未准备好且计算尚未开始,调用者将开始计算并将结果包装在 Future 中以供其他调用者使用。

这一切都可以通过 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());
        }
    }
  }
}

关于java - 对 Future.get() block 的方法调用。这真的很可取吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31092067/

相关文章:

c# - 关于处理从线程抛出的对象的事件的问题

c++ - 使用类对象提升线程 worker

javascript - Nodejs 串联运行函数

python - 如何限制 Python 线程?

javascript - 如何在 JavaScript 中组装异步请求的结果

c# - 异常在异步代码块中被忽略

java - JNI : NoSuchFieldError

java - 如何访问src目录下指定的现有文件夹中的文件?

Java 替换不成对的双引号

java - JBoss JMS 存储队列文件