如何在Java中实现非阻塞的Futures

5
Java Future对象用于获取由并行线程(Executors)执行的异步计算结果。我们调用Future.get()方法并等待结果准备就绪。此示例展示了一种从未来中检索结果的非阻塞方式。java-implement-java-non-blocking-futures
NonBlockingExecutor executor = new NonBlockingExecutor(Executors.newSingleThreadExecutor());

NonBlockingFuture<Integer> future = executor.submitNonBlocking(new Callable<Integer>() {

            @Override
            public Integer call() throws Exception {
                String threadName = Thread.currentThread().getName();
                System.out.println(threadName);
                //print -> pool-1-thread-1
                return 1;
            }
});

future.setHandler(new FutureHandler<Integer>() {

       @Override
       public void onSuccess(Integer value) {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName);
            //print -> pool-1-thread-1
       }

       @Override
       public void onFailure(Throwable e) {
            System.out.println(e.getMessage());
       }
 });

 Thread.sleep(50000);

在并行执行完成后,将调用此onSuccess()方法。问题是,onSuccess()方法不在主线程上运行。我想在主线程上执行onSuccess()方法。我该如何解决这个问题。谢谢。


1
很可能,你的主线程正在忙于做其他事情。 - Sotirios Delimanolis
说实话,我不知道如何使用执行器来处理这个问题。如果其他方法都失败了,你总可以“黑客式”地解决它 - 只需将一些数据传递到集合中,然后主线程就会看到这个集合中的数据并做出相应的响应。 - KookieMonster
我们能否使用Java 8 CompletableFuture来实现这个功能? - Tharanga
请参考这个问题:https://dev59.com/n10Z5IYBdhLWcg3wwyne - Ravindra babu
3个回答

8

这可以使用CompletableFutures实现。

    CompletableFuture.runAsync(() -> {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName);
        //print -> pool-1-thread-1
    }).whenComplete((task, throwable) -> {
        if(throwable != null) {
           System.out.println(e.getMessage());
        } else {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName);
            //print -> pool-1-thread-1
        }
    });

这里需要注意的是,将来会在执行线程上而不是提交线程上运行whenComplete任务。

runAsync 需要 API 等级 >= N。 - Mrinmoy

3
Future 的意义在于将相关的计算操作放在一个单独的线程中执行。 onSuccess 方法是让该单独线程表示它已经完成计算的一种方式。由于主线程不执行计算并且不知道计算何时完成,因此主线程调用onSuccess没有任何意义。
如果你想从主线程等待计算完成并获取结果,可以调用get()方法。如果你想检查计算是否已经完成,如果还未完成,则继续执行其他任务,可以调用isDone()get(long, TimeUnit)方法。如果要无论计算是否完成都要终止计算,可以调用cancel()方法。

1
谢谢。是的,你说得对,但是get()是一个阻塞操作。我们可以使用CompletableFuture来解决这个问题,但是我又遇到了同样的问题。结果没有在主线程上处理。CompletableFuture - Tharanga
我提到的其他选项是非阻塞或仅阻塞有限时间。 - Warren Dew

2

我希望在主线程上执行onSuccess()方法。我该怎么办?

你做不到。Java中没有任何东西可以让一个线程停止它正在做的事情,暂时做其他事情,然后回到它之前做的事情。一些编程环境有这样的功能——Unix信号,硬件中断——但这不是Java语言的一部分。


错误的。你可以在Java中使用Object的wait(timeout)方法来实现。 - Vladimir Nabokov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接