ListenableFuture

本文深入解析Guava库中的ListenableFuture接口,对比其与JDK concurrent包下Future接口的区别,并详细说明如何创建和使用ListenableFuture。通过实际例子展示了如何将ExecutorService转换为ListeningExecutorService,并在多线程环境中使用Callable任务,同时介绍了添加监听器以捕获成功或失败的回调方法。
转载自:http://www.cnblogs.com/hupengcool/p/3991310.html

ListenableFuture的说明

       Guava定义了ListenableFuture接口并继承了JDK concurrent包下的Future接口,ListenableFuture允许注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用,或者在运算(多线程执行)完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent中的Future是不支持的。在高并发并且需要大量Future对象的情况下,推荐尽量使用ListenableFuture来代替。
       ListenableFuture中的基础方法是addListener(Runnable, Executor), 该方法会在多线程运算完的时候,在Executor中执行指定的Runnable。

ListenableFuture的创建和使用

        对应JDK中的ExecutorService.submit(Callable)提交多线程异步运算的方式,Guava 提供了ListeningExecutorService接口, 该接口返回 ListenableFuture,而相应的ExecutorService返回普通的Future。将 ExecutorService 转为ListeningExecutorService,可以使用MoreExecutors.listeningDecorator(ExecutorService)进行装饰。

举例说明:
ListeningExecutorService pool = MoreExecutors
      .listeningDecorator(Executors.newFixedThreadPool(7));
向这个ListeningExecutorService提交Callable任务
ListenableFuture<String> future = pool.submit(new Callable<String>() {
	@Override
	public String call() throws Exception {
		Thread.sleep(1000 * 3);
		return "Task done !";
	}
});
添加Listener:
Futures.addCallback(future, new FutureCallback<String>() {
	@Override
	public void onSuccess(String result) {
		System.out.println(result);
	}

	@Override
	public void onFailure(Throwable t) {
		t.printStackTrace();
	}
});

当future任务正常执行完毕后,就会调用onSuccess()方法。









<think>首先,用户的问题是:“我想查找ListenableFuture的使用方法或示例代码请问ListenableFuture使用方法示例代码Guava”。这意味着用户需要关于Guava库中ListenableFuture的使用方法和代码示例。根据系统指令:-我需要使用中文回答。-结构化清晰,帮助用户逐步解决问题。-行内数学表达式用$...$,但这个问题是关于编程的,没有数学内容,所以我可能不需要数学格式。-独立公式用$$...$$,同样,不适用。-LaTeX语法正确,确保代码块显示正常。-生成相关问题。-引用标识添加在引用的段落末尾。-回答要真实可靠,基于提供的引用。提供的引用:-[1]:提到ListenableFuture,建议使用它而不是Future,如果必须转换,用JdkFutureAdapters.listenInPoolThread。-[2]:给出方法一使用addListener添加Runnable。-[3]:显示ListenableFuture接口定义,有addListener方法。用户上一次的问题是关于ListenableFuture的,所以我需要基于此回答。结构化回答:1.**介绍ListenableFuture**:简要解释是什么以及为什么有用。2.**使用方法**:描述如何使用addListener方法。3.**示例代码**:提供代码示例,基于引用[2]。4.**其他方法**:提到其他方式,比如addCallback(如果适用),但引用中主要提到addListener。5.**总结**:鼓励使用ListenableFuture。6.**相关问题**:生成相关问题。确保回答真实可靠:基于Guava官方文档,参考提供的引用。代码示例:从引用[2]中,有addListener的示例。我需要将其转化为可读的代码块。在Markdown中,使用```python或```java来表示代码块。因为这是Java,所以用```java。添加引用标识:比如在引用信息后添加[^2]。生成相关问题:最后部分加上“§§相关问题§§”,然后列出几个问题,如用户之前的需求。具体回答结构:1.开头:简述ListenableFuture在Guava中的用途。-ListenableFuture是Guava库对JavaFuture的增强,提供了更方便的异步处理方式,比如添加回调监听器。2.使用方法:-使用addListener方法注册一个Runnable,当Future完成时执行。3.示例代码:-提供引用[2]中的代码示例,稍作修改使其更完整。4.其他注意事项:-提到如果从Future转换,用JdkFutureAdapters.listenInPoolThread。5.结束语。6.相关问题。相关问题:1.ListenableFuture与CompletableFuture的区别是什么?2.如何取消ListenableFuture的任务?3.Guava中还有其他异步处理工具吗?确保回答中引用添加标识:-当直接引用文本时,加在末尾。</think> ### ListenableFuture 使用方法与示例代码(Guava) ListenableFuture 是 Google Guava 库中对 Java `Future` 接口的增强,它允许开发者添加回调函数(listener),在异步任务完成时自动执行操作,避免了传统 `Future.get()` 的阻塞问题。这提高了异步编程的效率和可维护性。以下我将逐步介绍其使用方法,并提供完整的示例代码。 #### 1. ListenableFuture 的基本使用方法 ListenableFuture 的核心方法是通过 `addListener()` 添加一个监听器(`Runnable`)。当异步任务完成时,监听器会在指定的 `Executor` 线程池中运行。使用步骤: - **创建 ListenableFuture**:通过 Guava 的 `ListeningExecutorService` 从 `ExecutorService` 包装得到。 - **添加监听器**:调用 `addListener()` 方法,传入一个 `Runnable` 来处理结果,同时指定一个线程池 `Executor`。 - **处理结果**:在 `Runnable` 的 `run()` 方法中,通过 `future.get()` 获取结果(需处理 `InterruptedException` 和 `ExecutionException` 异常)。 如果必须从基于 `Future` 的 API 转换为 ListenableFuture,可以使用 `JdkFutureAdapters.listenInPoolThread()` 进行硬编码转换,但建议优先直接使用 ListenableFuture[^1]。 #### 2. 示例代码 以下是一个完整的 Java 示例代码,基于引用[2]中的方法。代码演示了如何使用 `addListener()` 来处理异步计算结果。 ```java import com.google.common.util.concurrent.*; import java.util.concurrent.*; public class ListenableFutureExample { public static void main(String[] args) { // Step 1: 创建线程池和 ListeningExecutorService ExecutorService executorService = Executors.newFixedThreadPool(2); ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService); // Step 2: 提交异步任务,返回 ListenableFuture ListenableFuture<Integer> listenableFuture = listeningExecutorService.submit(() -> { // 模拟耗时任务:计算斐波那契数列 return computeFibonacci(10); // 以计算斐波那契数列第10项为例 }); // Step 3: 添加监听器,使用 addListener 方法 listenableFuture.addListener(new Runnable() { @Override public void run() { try { // 当任务完成时,获取结果 int result = listenableFuture.get(); System.out.println("任务完成,结果: " + result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }, executorService); // 指定在同一个线程池中运行 // 关闭线程池(实际应用中可能需要优雅关闭) executorService.shutdown(); } // 辅助方法:计算斐波那契数列 private static int computeFibonacci(int n) { if (n <= 1) return n; return computeFibonacci(n-1) + computeFibonacci(n-2); } } ``` **代码解释:** - **创建 ListenableFuture**:通过 `MoreExecutors.listeningDecorator()` 将普通 `ExecutorService` 包装为 `ListeningExecutorService`。调用 `submit()` 方法提交一个 `Callable` 任务(这里模拟计算斐波那契数列),返回 `ListenableFuture<Integer>`。 - **添加监听器**:`addListener()` 的第一个参数是 `Runnable`,在任务完成时自动触发 `run()` 方法。内部用 `future.get()` 获取结果(注意:如果任务失败,`ExecutionException` 会被抛出)。第二个参数是指定监听器运行的线程池(这里重用主线程池)。通过输出语句显示结果,避免阻塞主线程[^2]。 - **接口定义**:ListenableFuture 接口扩展了 Java 的 `Future`,并添加了 `void addListener(Runnable listener, Executor executor)` 方法[^3]。 #### 3. 其他常用方法 除了 `addListener()`,Guava 还提供了更便捷的 `Futures.addCallback()` 方法(需使用 `Futures` 工具类),它允许添加成功和失败的回调函数。但本例聚焦于 `addListener()` 的核心用法。 #### 结论 ListenableFuture 是优化异步编程的有效工具,尤其适用于需要在后台任务完成后更新UI或处理数据的场景。直接使用它可以避免 `Future.get()` 的阻塞风险,提高代码响应性[^1]。建议在实践中优先选择 ListenableFuture
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值