[英]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);
如果您想要某種類型安全,可以使用姐妹Guava com.google.common.eventbus
包中的EventBus
組合2個不同的獨立任務的結果
例如,讓我們假設你們其中一個Futures
返回Integer
而另一個返回Double
。
首先,創建一個累加器(其他名稱構建器 , 收集器等)類,您將使用EventBus注冊為事件接收器。 正如你所看到的,它真的是一個POJO,它將會進行Integer
和Double
事件
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.