尝试一下Guava带返回值的多线程处理类ListenableFuture

文章目录

最近在学习,Java实现异步编程的8种方式这篇博客的时候,没有找到比较好的一个学习demo,故在此整理一下。

ListenableFuture,带返回值的Guava多线程处理工具类

ListenableFuture是Java中的一个接口,它继承自java.util.concurrent.Future接口。ListenableFuture主要用于异步计算场景,允许在计算完成后添加回调函数(Callback),从而实现对异步任务执行结果的监听和处理。

与普通的Future不同,ListenableFuture提供了一种更加灵活且易于使用的方式来处理并发操作。当你提交一个任务到ExecutorService时,会返回一个ListenableFuture对象。这个对象表示将来某个时间点上可用的结果,并允许你在该结果可用时触发回调函数。

为了实现这一功能,ListenableFuture提供了两个关键方法:

  1. addListener(Runnable listener, Executor executor):此方法允许用户向ListenableFuture注册一个Runnable类型的监听器,在异步任务完成时由指定的executor执行。
  2. addCallback(FutureCallback<? super V> callback, Executor executor):此方法允许用户向ListenableFuture注册一个带有成功和失败处理逻辑的回调函数,在异步任务完成或出错时由指定的executor执行。

Google Guava库提供了对ListenableFutures进行操作、转换和组合等高级功能支持。例如:

  • Futures.transform():基于原始 ListenableFuture 的值创建新 ListenableFutures。
  • Futures.allAsList() 和 Futures.successfulAsList():将多个 ListenableFutures 组合成单个 Future。
  • Futures.immediate* 系列方法:创建已经具备特定值或异常状态下立即完成的 ListenableFutures。

总之,ListenableFuture提供了一种更加灵活、高效且易于使用的方式来处理并发操作和异步任务。它允许开发者在计算完成后添加回调函数,从而实现对异步任务执行结果的监听和处理。

举个例子

下面是一个使用ListenableFuture的示例,其中在for循环中提交了多个任务:

java 复制代码
import com.google.common.util.concurrent.*;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

public class ListenableFutureDemo {

    public static void main(String[] args) {
        // 创建一个线程池
        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));

        // 用于存储所有的ListenableFuture对象
        List<ListenableFuture<String>> futures = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            final int taskId = i;

            Callable<String> task = () -> {
                Thread.sleep(1000); // 模拟耗时操作
                return "Task " + taskId + " completed";
            };

            ListenableFuture<String> future = executorService.submit(task);
            Futures.addCallback(future, new FutureCallback<>() {
                @Override
                public void onSuccess(String result) {
                    System.out.println("Success: " + result);
                }

                @Override
                public void onFailure(Throwable t) {
                    System.err.println("Error occurred while executing task " + taskId);
                    t.printStackTrace();
                }
            }, MoreExecutors.directExecutor());

            futures.add(future);
        }

        try {
          // 等待所有任务完成,并获取结果。
          List<String> results = Futures.allAsList(futures).get();
          System.out.println("All tasks completed successfully. Results: ");
          results.forEach(System.out::println);

          executorService.shutdown(); // 关闭线程池

      } catch (Exception e) {
          e.printStackTrace();
      }
    }
}

这个示例首先创建了一个ListeningExecutorService实例。然后,在for循环中创建并提交了10个Callable任务。每次迭代都会将新创建的ListenableFuture添加到futures列表中。

我们还为每个future添加了回调函数,以便在任务成功或失败时执行相应的操作。最后,我们等待所有future完成,并输出它们的结果。

扩展阅读

Java实现异步编程的8种方式

相关推荐
2301_780789662 小时前
跨平台适配!SDK 游戏盾兼容全终端游戏场景
java·网络·ddos
第九序言T2 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
学长毕设3 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
步行cgn3 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川3 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵3 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
程序喵大人3 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
秋天的怀念_David4 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas1004 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
niucloud-admin5 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php