【问题标题】:Finagle Future objects, are they reusable?Finagle 未来的对象,它们是可重用的吗?
【发布时间】:2012-10-16 20:19:17
【问题描述】:
我是 Finagle 的新手。我现在正在阅读某人的代码,发现 Future 对象在不同的连接操作中被重用。我的问题是这会导致 Future 对象被执行多次(在每个连接中),还是只会执行一次并存储结果以供以后连接?
例子:
Future<A> a= b
.join(c)
.flatMap(new SomeFunctionReturningA());
Future<Tuple2<A, B>> future1 = a.join(b);
Future<D> future2 = future1.flatMap(new SomeFunctionReturningD());
future2.get();
那么 b 会被执行两次,还是只执行一次?
【问题讨论】:
标签:
java
twitter
future
finagle
【解决方案1】:
我自己写了一个快速测试:
import com.twitter.util.Function;
import com.twitter.util.Future;
import java.util.Random;
import org.junit.Test;
import scala.Tuple2;
public class FinagleFutureTest {
int counter = 0;
@Test
public void test(){
Counter counter = new Counter();
Future<Counter> one = Future.value(counter).flatMap(new IncrementFunction());
Future<Counter> two = one.flatMap(new IncrementFunction());
Future<Tuple2<Counter, Counter>> three = two.join(one);
Tuple2<Counter, Counter> tuple = three.flatMap(new TupleFunction()).get();
System.out.println("one: "+ tuple._2().count+", "+tuple._2().randomInt);
System.out.println("two: "+ tuple._1().count+", "+tuple._1().randomInt);
}
static class TupleFunction extends Function<Tuple2<Counter, Counter>, Future<Tuple2<Counter, Counter>>>{
@Override
public Future<Tuple2<Counter, Counter>> apply(Tuple2<Counter, Counter> t1) {
return Future.value(t1);
}
}
static class IncrementFunction extends Function<Counter, Future<Counter>>{
@Override
public Future<Counter> apply(Counter counter) {
counter.add();
return Future.value(counter);
}
}
static class Counter{
public int count = 0;
public int randomInt;
Counter(){
Random random = new Random();
randomInt = random.nextInt();
}
public void add(){
count++;
}
}
}
结果如下:
one: 2, 2009034289
two: 2, 2009034289
所以结论是Future对象不管参与多少join操作都只会执行一次。
【解决方案2】:
Future 只是一个值的容器,并且该值只会被设置一次!
Future[T] 有不同的状态:
当您在 Future A 上使用 map/flatMap 和函数 f 时,您只需创建一个新的 Future B,它将是前一个由函数 f 转换的结果。
注意:
- 如果未来
A 尚未“填充”,您将有一个尚未填充的B
- 在
A 中设置值a 的线程也将执行f(a) 并在B 中设置值
- 如果
A 已经“填充”,那么map/flatMap 的调用者也将执行f(a),但它不会重新计算A 的值。
- 您也可以使用
onSuccess/onFailure,它只会注册一些代码,以便在未来获得其值时执行。
【解决方案3】:
Future 对象只执行一次。
Finagle 使用 com.twitter.util.A Future 是一个尚不可用的值的句柄。
使用 Future 的两种最基本的方法是:
阻塞并等待计算返回
注册一个回调,当计算最终成功或失败时调用
FuturePool 对象使您能够在其自己的线程上放置阻塞操作。
您可以通过twitter blog和fingale github对Finagle Future(Future Pool)有更多的了解