如何在Java中创建一个已完成的Future

114
什么是在Java中构建已完成future的最佳方法?我已经实现了自己的CompletedFuture,但希望找到已存在的类似解决方案。
public class CompletedFuture<T> implements Future<T> {
    private final T result;

    public CompletedFuture(final T result) {
        this.result = result;
    }

    @Override
    public boolean cancel(final boolean b) {
        return false;
    }

    @Override
    public boolean isCancelled() {
        return false;
    }

    @Override
    public boolean isDone() {
        return true;
    }

    @Override
    public T get() throws InterruptedException, ExecutionException {
        return this.result;
    }

    @Override
    public T get(final long l, final TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
        return get();
    }
}

1
最好的方法是不要创建一个!;-) 为什么需要实现一个Future?难道不能使用返回Future的现有对象吗? - assylias
1
我怀疑这样的东西不存在,因为我从未见过需要它的理由。也许你可以解释一下你想做什么? - Peter Lawrey
1
@PeterLawrey 我猜他需要它是为了一些 API,这些 API 由于某些扭曲的原因想要使用 futures,即使它实际上只需要其值。或者他需要它来进行模拟。至少这是我能想到的唯一原因。 - Cubic
13
单元测试是希望实现这个的一个很好的理由——使用模拟服务返回包含测试值的Future。 - Louis Wasserman
3
如果你有一个接受Callable<T>的方法,并且根据可用资源或已提前提供的选项等因素可能异步运行作业或不运行作业,那会怎么样?想象一下,如果Executor.execute(Runnable)以参数的形式接受Callable<T>并决定在执行线程中运行它,那么实现是否需要创建自己的Future<T>呢? - Martin Andersson
3
我有同样的需求并可以解释一下... 我正在编写的代码期望一个Future列表,表示显然同时执行的查询结果。然而,在每种情况下,查询结果可能会被缓存,当它被缓存时,我的代码返回缓存结果的CompletedFuture。这提供了干净的抽象和关注点分离。 - Alex Worden
6个回答

242

在Java 8中,您可以使用内置的CompletableFuture:

 Future future = CompletableFuture.completedFuture(value);

1
这将会给你一个已完成的future。相反地,请使用new CompletableFuture()。 - zafar142003
16
OP要求完成时态,对吧? - Andrejs
1
根据问题细节中的类(2012年),我认为OP想要一个“CompletableFuture”实现。但我猜现在这已经不重要了。 - zafar142003
从问题细节中的类来看,似乎OP想要一个具有立即值的Future。请注意,isDone始终返回true。因此,这是一个很好的答案。 - nathanfranke
请注意,CompletableFutureListenableFuture不兼容;如果您需要一个监听器,您可能需要考虑基于ListenableFuture的其他实现方式。 - Eric Dand

70

Apache Commons Lang定义了一个类似的实现,称为ConstantFuture,您可以通过调用以下方法来获取它:

Future<T> future = ConcurrentUtils.constantFuture(T myValue);

1
请看下面Andrejs的答案,可能更符合你的需求。 - nathanfranke

44

5
FutureTask<String> ft = new FutureTask<>(() -> "foo");
ft.run();

System.out.println(ft.get());

将打印出"foo";

您还可以拥有一个在调用get()时抛出异常的Future:

FutureTask<String> ft = new FutureTask<>(() -> {throw new RuntimeException("exception!");});
ft.run();

-3

我在Java的rt.jar中找到了一个非常类似于你的类的东西

com.sun.xml.internal.ws.util.CompletedFuture

它允许您指定在调用get()时可能抛出的异常。如果您不想抛出异常,只需将其设置为null即可。


3
通常情况下,使用 com.sun.* 包中的任何内容都不是一个好主意。这些类通常被认为是内部实现细节,并且在Java版本之间很可能发生变化。 - James Kingsbery

-6
在Java 6中,您可以使用以下内容:
Promise<T> p = new Promise<T>();
p.resolve(value);
return p.getFuture();

3
我不认为这是Java核心库中的内容。它使用了哪个外部依赖关系? - Jorn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接