尝试一下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种方式

相关推荐
浮游本尊10 小时前
Java学习第22天 - 云原生与容器化
java
渣哥12 小时前
原来 Java 里线程安全集合有这么多种
java
间彧12 小时前
Spring Boot集成Spring Security完整指南
java
间彧13 小时前
Spring Secutiy基本原理及工作流程
java
Java水解14 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆16 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学16 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole16 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊16 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端