并发编程是一个难题,可是一个强大而简单的抽象能够显著的简化并发的编写。出于这样的考虑,Guava 定义了 ListenableFuture接口并继承了JDK concurrent包下的Future 接口,ListenableFuture 容许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用, 或者在运算(多线程执行)完成后当即执行。这样简单的改进,使得能够明显的支持更多的操做,这样的功能在JDK concurrent中的Future是不支持的。 在高并发而且须要大量Future对象的状况下,推荐尽可能使用ListenableFuture来代替..java
ListenableFuture 中的基础方法是addListener(Runnable, Executor), 该方法会在多线程运算完的时候,在Executor中执行指定的Runnable。编程
对应JDK中的 ExecutorService.submit(Callable) 提交多线程异步运算的方式,Guava 提供了ListeningExecutorService 接口, 该接口返回 ListenableFuture, 而相应的ExecutorService 返回普通的 Future。将 ExecutorService 转为 ListeningExecutorService,可使用MoreExecutors.listeningDecorator(ExecutorService)进行装饰。举例说明:多线程
ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
而后咱们能够向这个ListeningExecutorService提交Callable任务并发
final ListenableFuture<String> future = pool.submit(new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(1000*3); return "Task done !"; } });
而后咱们添加Listener:异步
future.addListener(new Runnable() { @Override public void run() { try { final String contents = future.get(); System.out.println(contents); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }, MoreExecutors.sameThreadExecutor());
咱们看看上面的代码,确实不怎么优雅,咱们须要处理抛出的异常,须要本身经过future.get()得到前面计算的值。有没有更加简便的方法呢?固然有,Guava提供了一个简便方法来替代上面的写法:ide
Futures.addCallback(future, new FutureCallback<String>() { @Override public void onSuccess(String result) { System.out.println(result); } @Override public void onFailure(Throwable t) { t.printStackTrace(); } });
完成代码以下:高并发
package concurrency; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.Callable; import java.util.concurrent.Executors; /** * Created by hupeng on 2014/9/24. */ public class ListenableFutureTest { public static void main(String[] args) throws InterruptedException { ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); final ListenableFuture<String> future = pool.submit(new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(1000 * 2); return "Task done !"; } }); // future.addListener(new Runnable() { // @Override // public void run() { // try { // final String contents = future.get(); // System.out.println(contents); // } catch (InterruptedException e) { // e.printStackTrace(); // } catch (ExecutionException e) { // e.printStackTrace(); // } // } // }, MoreExecutors.sameThreadExecutor()); Futures.addCallback(future, new FutureCallback<String>() { @Override public void onSuccess(String result) { System.out.println(result); } @Override public void onFailure(Throwable t) { t.printStackTrace(); } }); Thread.sleep(5 * 1000); //wait for task done pool.shutdown(); } }