链接地址:http://www.xx566.com/detail/158.html
Java 5中引入了concurrent包,其中提供了许多重要的并发设计,其中一个便是Future对象,Future用于表示一个异步计算任务,我们通常需要 启动一个Executor实例,之后调用submit方法获取到Future对象,并通过future.get()方法获取线程执行完成后的结果,ListenableFuture接口继承了Future接口进行了扩展,允许我们注册一个Callback函数,并在任务完成后执行。
下面是个简单的Future调用示例:
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> future = executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
//这里调用一些处理逻辑
return 1 + 1;
}
});
更多Executor,请参阅:JavaSE_多线程 ,在上面的例子中,我们提交了一个Callable对象到ExecutorService实例,ExecutorService实例会立即返回Future对象,但是这并不意味着线程任务已经完成,要获取线程执行的结果,我们需要调用Future.get方法,但是如果任务并未完成的话会造成线程阻塞。
ListenableFuture接口继承了Future接口进行了扩展,允许我们注册一个Callback函数,并在任务完成后执行。翻开ListenableFuture接口的源码,我们看到其中只定义了一个addListener方法,我们可以通过ListenableFuture.addListener,传入一个Runnable线程和ExecutorService对象,这个ExecutorService对象可以是提交原始任务的Executor实例,或者是完全的ExecutorService实例。
获得ListenableFuture接口
我 们知道,当一个Callable对象提交后,ExecutorService接口会返回一个Future对象,那么我们应该怎样获取到 ListenableFuture对象以便于我们设置Callback回调函数呢?Guava通过ListentingExecutorService接 口包装了ExecutorService对象,如下:
ListeningExecutorService executorService =
MoreExecutors.listeningDecorator(executor);
这里我们使用到了MoreExecutors类,其中包含了大量的静态方法用于处理Executor, ExecutorService和ThreadPool实例,翻开源码,整理其中的公共方法,如下:
getExitingExecutorService( ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit):将给定的ThreadPoolExecutor转换成ExecutorService实例,在程序完成时退出, 它是通过使用守护线程和添加一个关闭钩子来等待他们完成。
getExitingScheduledExecutorService( ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit):将给定的ScheduledThreadPoolExecutor转换成ScheduledExecutorService实例,在程序完成时退出, 它是通过使用守护线程和添加一个关闭钩子来等待他们完成。
addDelayedShutdownHook( ExecutorService service, long terminationTimeout, TimeUnit timeUnit):添加一个关闭的钩子来等待给定的ExecutorService中的线程完成。
getExitingExecutorService(ThreadPoolExecutor executor):将给定的ThreadPoolExecutor转换成ExecutorService实例,在程序完成时退出, 它是通过使用守护线程和添加一个关闭钩子来等待他们完成。
getExitingScheduledExecutorService( ScheduledThreadPoolExecutor executor):将给定的ThreadPoolExecutor转换成ScheduledExecutorService实例,在程序完成时退出, 它是通过使用守护线程和添加一个关闭钩子来等待他们完成。
sameThreadExecutor():创建一个ExecutorService实例,运行线程中的每一个任务。
listeningDecorator( ExecutorService delegate):创建一个ExecutorService实例,通过线程提交或者唤醒其他线程提交ListenableFutureTask到给定的ExecutorService实例。
listeningDecorator( ScheduledExecutorService delegate):创建一个ScheduledExecutorService实例,通过线程提交或者唤醒其他线程提交ListenableFutureTask到给定的ExecutorService实例。
platformThreadFactory():返回一个默认的线程工厂用于创建新的线程。
shutdownAndAwaitTermination( ExecutorService service, long timeout, TimeUnit unit):逐渐关闭指定的ExecutorService,首先会禁用新的提交, 然后会取消现有的任务。
来看下面一个典型示例:
int NUM_THREADS = 10;//10个线程
executorService =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUM_THREADS));
ListenableFuture<String> listenableFuture =
executorService.submit(new Callable<String>(){
@Override
public String call() throws Exception {
return null;
}
});
listenableFuture.addListener(new Runnable() {
@Override
public void run() {
//在Future任务完成之后运行的一些方法
System.out.println("methodToRunOnFutureTaskCompletion");
}
}, executorService);
我们来对上面的代码做一个简单的解释:首先,我们使用ExecutorService实例创建了一个固定大小的线程池,然后我们将Callable对象提 交给ListeningExecutorService获取到我们需要的ListenableFuture实例,最后我们注册了一个回调函数在任务完成后 执行,值得注意的有一点,如果任务完成的时候我们设置回调方法,它将立即执行。
不过,ListenableFuture. addListener有一个小的缺陷,我们没有办法接收返回的对象,这就导致在任务执行失败或成功的时候,我们不能执行其他的操作,不过Guava 提供了FutureCallback接口来弥补这个缺陷,下一篇:Guava库学习:学习Concurrency(四)FutureCallback,敬请期待...
源码地址:http://git.oschina.net/realfighter/xx566-diary/blob/master/src/guava/ListenableFutureTest.java