11

我需要找到一种从 Future 转换为 ListenableFuture 的方法。目前我正在使用一个返回 Future 的服务,但我需要连接一个监听器。我无法更改服务接口,因为它不属于我。

有没有一种简单的方法可以做到这一点?

我已经阅读了番石榴文档,但我仍然找不到办法。

4

2 回答 2

22

Guava 提供了JdkFutureAdapters这种转换的类型。API状态_

使用提供普通 Future 实例的库所必需的实用程序。

例如

Future<?> future = ...;
ListenableFuture<?> listenable = JdkFutureAdapters.listenInPoolThread(future);

但是你应该小心使用它:当你已经提交了任务时,很难模拟可听的未来,因为没有办法在那里完成一个钩子,所以 Guava 需要一个新线程并在那里阻塞,直到原始Future完成。

Guava Wiki 也包含有关此特定案例的一些信息

于 2015-05-11T03:46:31.253 回答
0

Future 只是获取接口,而 Guava ListenableFuture 是 Future 接口,注册的 Runnable 监听器在 set 或 setException 时由 complete() 运行(由 guava AbstractFuture 实现)。

import com.google.common.util.concurrent.AbstractFuture;
import java.util.concurrent.Future;

public class ListenerFuture<V> extends AbstractFuture<V> {

    public ListenerFuture(Future<V> future){
        this.future= future;
    }
    // blocking in future get, then run listener in AbstractFuture set
    public void fireListener(){
        try {
            super.set(future.get());
        }catch (Exception e){
            throw new RuntimeException("guava set ListenableFuture", e);
        }
    }

    private Future<V> future;
}

ListenerFuture<V> response= new ListenerFuture(service.response());
response.addListener(Runnable, Executor);
// pass the ListenableFuture to whom need it
// do something else until who must have service response call the blocking
response.fileListner()

Guava AbstractFuture 有其局限性:

  1. 侦听器是列表,但通常只使用 1 个 - 矫枉过正。如果需要多个侦听器,请将其分叉到您的侦听器中,或者使用消息传递来考虑您的设计。
  2. setException 将返回值设置为异常,因此用户必须在 get() 处使用 instanceof 来区分异常与否
  3. 在 Future 管道中,过多的层 addListener() 使代码难以阅读。

我更喜欢 CompletableFuture.supply().thenApply().thenAccept().handle()

于 2021-08-27T16:08:51.393 回答