簡體   English   中英

使用兩種不同類型的Guava ListenableFutures的結果

[英]Use the results of two Guava ListenableFutures of different types

我有兩個在其他線程上完成的ListenableFutures。 每個未來都是不同的類型,我希望在它們完整時使用它們的兩個結果。

有沒有一種優雅的方式來處理這個使用番石榴?

如果您想要某種類型的安全性,您可以執行以下操作:

class Composite {
  public A a;
  public B b;
}

public ListenableFuture<Composite> combine(ListenableFuture<A> futureA, 
                                           final ListenableFuture<B> futureB) {

  return Futures.transform(futureA, new AsyncFunction<A, Composite>() {
    public ListenableFuture<Composite> apply(final A a) throws Exception {
      return Futures.transform(futureB, new Function<B, Compisite>() {
        public Composite apply(B b) {
          return new Composite(a, b);
        }
      }
    } 
  }

}

ListenableFuture<A> futureA = ...
ListenableFuture<B> futureB = ...

ListenableFuture<Composite> result = combine(futureA, futureB);

在這種情況下Pair<A, B>如果您願意Pair<A, B> Composite可以是來自Apache Commons的Pair<A, B>

此外,未來任何一方的失敗都將導致未來的合並失敗。

另一個解決方案是看看Spotify團隊的Trickle GitHub自述文件有一個示例,顯示了類似問題的解決方案。

毫無疑問是其他解決方案,但這是我腦海中浮現的解決方案。

Runnable listener = new Runnable() {
    private boolean jobDone = false;

    @Override
    public synchronized void run() {
        if (jobDone || !(future1.isDone() && future2.isDone())) {
            return;
        }
        jobDone = true;
        // TODO do your job
    }
};
future1.addListener(listener);
future2.addListener(listener);

不是很優雅,但應該做的工作。

或者,更優雅,但你需要演員表:

ListenableFuture<List<Object>> composedFuture = 
    Futures.allAsList(future1, future2);

自Guava v20.0起,您可以使用:

ListenableFuture<CombinedResult> resultFuture =
   Futures.whenAllSucceed(future1, future2)
       .call(callableThatCombinesAndReturnsCombinedResult, executor);

請看這里的java docs示例

如果您想要某種類型安全,可以使用姐妹Guava com.google.common.eventbus包中的EventBus組合2個不同的獨立任務的結果

例如,讓我們假設你們其中一個Futures返回Integer而另一個返回Double

首先,創建一個累加器(其他名稱構建器收集器等)類,您將使用EventBus注冊為事件接收器。 正如你所看到的,它真的是一個POJO,它將會進行IntegerDouble事件

class Accumulator
{
    Integer intResult;
    Double  doubleResult;

    @Subscribe // This annotation makes it an event handler
    public void setIntResult ( final Integer val )
    {
        intResult = val;
    }

    @Subscribe
    public void setDoubleResult ( final Double val )
    {
        doubleResult = val;
    }
}

以下是將采用2期貨的方法的實現,並將它們組合成累加器。

final ListenableFuture< Integer > future1 = ...;
final ListenableFuture< Double > future2 = ...;

final ImmutableList< ListenableFuture< ? extends Object> > futures =
    ImmutableList.< ListenableFuture<? extends Object> >of( future1, future2 );

final ListenableFuture< Accumulator > resultFuture =
    Futures.transform(
        // If you don't care about failures, use allAsList
        Futures.successfulAsList( futures ),
        new Function< List<Object>, Accumulator > ( )
        {
            @Override
            public Accumulator apply ( final List< Object > input )
            {
                final Accumulator accumulator = new Accumulator( );

                final EventBus eventBus = new EventBus( );
                eventBus.register( accumulator );

                for ( final Object cur: input )
                {
                    // Failed results will be set to null
                    if ( cur != null )
                    {
                        eventBus.post( cur );
                    }
                }

                return accumulator;
            }
        }
    );

final Accumulator accumulator = resultFuture.get( );

這是一個簡單的例子,可以添加2個可聽的期貨:

//Asynchronous call to get first value
final ListenableFuture<Integer> futureValue1 = ...;

//Take the result of futureValue1 and transform it into a function to get the second value
final AsyncFunction<Integer, Integer> getSecondValueAndSumFunction = new AsyncFunction<Integer, Integer>() {
    @Override
    public ListenableFuture<Integer> apply(final Integer value1) {

        //Asynchronous call to get second value
        final ListenableFuture<Integer> futureValue2 = ...;


        //Return the sum of the values
        final Function<Integer, Integer> addValuesFuture = new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer value2) {

                Integer sum = value1 + value2;
                return sum;
            }               
        };              

        //Transform the second value so its value can be added to the first
        final ListenableFuture<Integer> sumFuture = Futures.transform(futureValue2, addValuesFuture);   

        return sumFuture;
    }
};

final ListenableFuture<Integer> valueOnePlusValueTwo = Futures.transform(futureValue1, getSecondValueAndSumFunction);   

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM