如何在ListenableFuture中的future.isDone()中调用Java保证回调

时间:2017-11-15 20:58:50

标签: java asynchronous guava

在浏览ListenableFutre界面时,会在文档中注明

  

addListener()

     

注册要在给定执行程序上运行的侦听器。听众   将在Future的计算完成时运行,或者如果是。{   计算已经完成,立即。

由于Future.get()是一个阻塞调用,Java如何保证某些未来是完成的?他们在旋转吗?我理解使用像dagger生成器这样的框架,它有点容易理解(一旦完成任务,写入某些东西,监控线程将被通知)。在ListenableFuture案例中,jvm是否支持这样的开箱即用?

使用wait()/notify()类似机制?

FollowUp Question :就像你们所有人所说的那样,调用者实际上保证了监听器的运行,正常情况下使用ListenableFutureListenableFuture future = Caller.call(),调用者和被调用者在不同的线程中,甚至在不同的JVM中,如何在java中完成?监听器存储在调用者线程和被调用者线程中?或者在不同的JVM中使用远程reigstery?

3 个答案:

答案 0 :(得分:2)

ListenableFuture没有什么神奇之处 - 接口的契约只要求任何实现在完成时调用任何已注册的侦听器(或者如果已经完成则立即调用)。

查看一个这样的实现AbstractFuture可能会有所帮助 - 具体看一下.complete() method,它将在未来变为"完成后立即调用" (通过完成,失败或被取消)。为了兼顾快速和线程安全,细节有点复杂,但基本上就是这样。

答案 1 :(得分:1)

如前所述,了解ListenableFuture的最佳方法是查看它是如何实现的。当您调用addListener(Runnable listener, Executor exec)时,您提供了一个Runnable侦听器和一个Executor来运行此侦听器,因此您决定如何执行侦听器。

  

监听器存储在调用者线程和被调用者线程中?

侦听器存储在未来的ExecutionList

// The execution list to hold our executors.
private final ExecutionList executionList = new ExecutionList();

addListener(Runnable listener, Executor exec)就是这样:

public void addListener(Runnable listener, Executor exec) {
    executionList.add(listener, exec);
}

因此,当未来完成时,它会调用set(V value)方法:

protected boolean set(@Nullable V value) {
    boolean result = sync.set(value);
    if (result) {
      executionList.execute();
    }
    return result;
}

并且所有侦听器都执行如下:executor.execute(runnable);

答案 2 :(得分:0)

我想补充答案。

番石榴并不保证。 如果您关闭JVM或JVM崩溃,则不会调用任何侦听器。 如果在不取消期货的情况下关闭执行程序,则也不会调用任何侦听器。我的意思是这个案子:

ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(false);
        return t;
    }
});
ListenableFuture<?> listenableFuture = JdkFutureAdapters.listenInPoolThread(
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("run!!!");
            }
        }),
        executorService
);
Futures.addCallback(listenableFuture, new FutureCallback<Object>() {

    @Override
    public void onSuccess(@Nullable Object result) {
        System.out.println("onSuccess");
    }

    @Override
    public void onFailure(Throwable t) {
        System.out.println("onFailure");
    }
});
MoreExecutors.shutdownAndAwaitTermination(executorService, 3, TimeUnit.SECONDS);

我没有看到“onSuccess”或“onFailure”,是吗?

在JVM运行的常规工作流程中,Guava使用CAS只调用一次侦听器,您也可以在源代码中看到它。