Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ListenableFuture回调执行顺序_Java_Parallel Processing_Java 7_Guava - Fatal编程技术网

Java ListenableFuture回调执行顺序

Java ListenableFuture回调执行顺序,java,parallel-processing,java-7,guava,Java,Parallel Processing,Java 7,Guava,Guava的ListenableFuture库提供了一种向未来任务添加回调的机制。具体做法如下: ListenableFuture<MyClass> future = myExecutor.submit(myCallable); Futures.addCallback(future, new FutureCallback<MyClass>() { @Override public void onSuccess(@Nullable MyClass myCla

Guava的
ListenableFuture
库提供了一种向未来任务添加回调的机制。具体做法如下:

ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
    @Override
    public void onSuccess(@Nullable MyClass myClass) {
      doSomething(myClass);
    }

    @Override
    public void onFailure(Throwable t) {
      printWarning(t);
    }}, myCallbackExecutor);
}
final Builder b;
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
  @Override
  public void onSuccess(@Nullable MyClass myClass) {
    b.setMyClass(myClass);
  }

  @Override
  public void onFailure(Throwable t) {
    printWarning(t);
  }}, myCallbackExecutor);
}
// Do the same thing for all other fields.
我的问题是,是否保证在
get
终止之前运行某个未来的所有回调。也就是说,如果将来注册了多个回调执行器上的多个回调,那么所有回调是否会在
get
返回之前完成

编辑

我的用例是,我将构建器传递给许多类。每个类填充生成器的一个字段。我希望异步填充所有字段,因为每个字段都需要一个外部查询来生成字段的数据。我希望调用我的
asyncPopulateBuilder
的用户收到一个
Future
,她可以在上面调用
get
,并确保所有字段都已填充。我的想法如下:

ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
    @Override
    public void onSuccess(@Nullable MyClass myClass) {
      doSomething(myClass);
    }

    @Override
    public void onFailure(Throwable t) {
      printWarning(t);
    }}, myCallbackExecutor);
}
final Builder b;
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);
Futures.addCallback(future, new FutureCallback<MyClass>() {
  @Override
  public void onSuccess(@Nullable MyClass myClass) {
    b.setMyClass(myClass);
  }

  @Override
  public void onFailure(Throwable t) {
    printWarning(t);
  }}, myCallbackExecutor);
}
// Do the same thing for all other fields.
final Builder b;
ListenableFuture=myExecutor.submit(myCallable);
Futures.addCallback(future,newfuturecallback(){
@凌驾
成功时公共无效(@Nullable MyClass MyClass){
b、 设置myClass(myClass);
}
@凌驾
失效时的公共无效(可丢弃的t){
打印警告(t);
}},myCallbackExecutor);
}
//对所有其他字段执行相同的操作。

在这种情况下,在填充所有字段之前,建议使用什么方法进行阻止?

get
返回之前,不保证运行回调。下面将详细介绍

至于如何解决这个用例,我建议将每个字段数据的查询转换为单独的
未来
,将它们与
allAsList
+
transform
相结合,并对此采取行动。(我们可能有一天会提供。)

ListenableFuture=myExecutor.submit(myCallable);
最终名单未来富=
期货市场转型(
未来,,
新函数(){…},
myCallbackExecutor);
最终列出的未来条形图=。。。;
最终可上市未来baz=。。。;
ListenableFuture allAvailable=Futures.allAsList(foo、bar、baz);
ListenableFuture allSet=Futures.transform(
所有可用的,
新函数(){
@凌驾
应用公共对象(忽略对象){
//使用getUnchecked,因为我们知道他们已经成功了:
builder.setFoo(Futures.getUnchecked(foo));
builder.setFoo(Futures.getUnchecked(bar));
builder.setFoo(Futures.getUnchecked(baz));
返回null;
}
}
};
现在用户可以调用
allSet.get()
等待填充

(或者您希望
allSet
成为
Future
,以便将引用传递给构建器。或者您根本不需要
Future
的完整版本,只需要
countdownlock
,在该版本中,您可以使用
addCallback
而不是
transform
,并在最后对闩锁进行倒计时。)回调。)

这种方法还可以简化错误处理


回复:“回调是否在
get
之前运行?”

首先,我非常确定,我们在规范中的任何地方都不能保证这一点,因此感谢您的提问,而不仅仅是为了:)如果您最终希望依赖当前实现的某些行为,请让我们添加文档和测试

第二,如果我从字面上理解你的问题,你所要求的是不可能的:如果
get()
等待所有侦听器完成,那么任何调用
get()
的侦听器都将挂起

您的问题的一个稍微宽松的版本是“所有侦听器是否至少在
get()
返回之前启动?”这也是不可能的:假设我将两个侦听器附加到同一
Future
上,以便与
directExecutor()
一起运行。两个侦听器只需调用
get()
并返回。其中一个侦听器必须首先运行。当它调用
get()
时,它将挂起,因为第二个侦听器还没有启动——在第一个侦听器完成之前,它也不能启动。(更一般地说,依赖任何给定的
执行器来迅速执行任务可能是危险的。)

更宽松的版本是“在
get()
返回之前,
Future
是否至少为每个侦听器调用
submit()
”,但这最终会在与我刚才描述的相同的场景中出现问题:在
directExecutor()上调用
submit(firstListener)
运行任务并调用
get()
,在启动第二个侦听器之前无法完成,在第一个侦听器完成之前无法完成

如果说有什么区别的话,那就是在任何侦听器执行之前,
get()
将返回的可能性似乎要大得多。但是由于线程调度的不可预测性,我们也不能依赖它。(再说一次:它没有文档化,所以请不要依赖它,除非您要求对它进行文档化!)

final Builder b;
CountDownLatch闩锁=新的CountDownLatch(1);
ListenableFuture=myExecutor.submit(myCallable);
Futures.addCallback(future,newfuturecallback(){
@凌驾
成功时公共无效(@Nullable MyClass MyClass){
b、 设置myClass(myClass);
倒计时();
}
@凌驾
失效时的公共无效(可丢弃的t){
打印警告(t);
倒计时();
},myCallbackExecutor);
试一试{
satch.wait();
}捕捉(中断异常e){
LOG.error(“某物中断异常”,e);
}最后{
myCallbackExecutor.shutdown();
}
编辑

代码的灵感来自@Chris Povirk

(或者您希望allSet成为未来,这样用户就可以获得对构建器的引用。或者您根本不需要一个完整的未来,只需要一个倒计时闩锁,您可以使用addCallback而不是transform,并在回调结束时倒计时闩锁。) 这种方法还可以简化错误处理

谢谢你的回答!
final Builder b;
CountDownLatch latch = new CountDownLatch(1);
ListenableFuture<MyClass> future = myExecutor.submit(myCallable);

Futures.addCallback(future, new FutureCallback<MyClass>() {
 @Override
 public void onSuccess(@Nullable MyClass myClass) {
 b.setMyClass(myClass);
 latch.countDown();
}
 @Override
 public void onFailure(Throwable t) {
 printWarning(t);
 latch.countDown();
}, myCallbackExecutor);

try {
        latch.await();
    } catch (InterruptedException e) {
        LOG.error("something InterruptedException", e);
    } finally {
        myCallbackExecutor.shutdown();
    }