java Guava ListenableFuture实现线程回调功能

38 篇文章 0 订阅
java Future具有局限性。在实际应用中,当需要下载大量图片或视频时,可以使用多线程去下载,提交任务下载后,可以从多个Future中获取下载结果,由于Future获取任务结果是阻塞的,所以将会依次调用Future.get()方法,这样的效率会很低。很可能第一个下载速度很慢,则会拖累整个下载速度。
Future主要功能在于获取任务执行结果和对异步任务的控制。但如果要获取批量任务的执行结果,从上面的例子我们已经可以看到,单使用 Future 是很不方便的。其主要原因在于:一方面是没有好的方法去判断第一个完成的任务;另一方面是 Future的get方法 是阻塞的,使用不当会造成线程的浪费。第一个问题可以用 CompletionService 解决,[color=red][b]CompletionService 提供了一个 take() 阻塞方法,用以依次获取所有已完成的任务。[/b][/color][color=blue][b]第二个问题可以用 Google Guava 库所提供的 ListeningExecutorService 和 ListenableFuture 来解决。[/b][/color]除了获取批量任务执行结果时不便,Future另外一个不能做的事便是防止任务的重复提交。要做到这件事就需要 Future 最常见的一个实现类 FutureTask 了。Future只实现了异步,而没有实现回调,主线程get时会阻塞,可以轮询以便获取异步调用是否完成。
在实际的使用中建议使用Guava ListenableFuture来实现异步非阻塞,目的就是多任务异步执行,通过回调的方方式来获取执行结果而不需轮询任务状态。


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

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;

public class ListenableTest {

public static void main(String[] args) {
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
final List<Long> value = new ArrayList<Long>();
List<ListenableFuture<Long>> futures = new ArrayList<ListenableFuture<Long>>();
for(long i=1;i<=3;i++){
// 处理线程逻辑
final ListenableFuture<Long> listenableFuture = executorService.submit(new AddCallable(1000000*(i-1)+1,i*1000000));
// 回调方法
Futures.addCallback(listenableFuture, new FutureCallback<Long>() {
@Override
public void onSuccess(Long result) {
value.add(result);
}

@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
futures.add(listenableFuture);
}
// 阻塞三个线程执行完成
Futures.allAsList(futures);
long result = 0 ;
for(int i=0,n=value.size();i<n;i++){
result += value.get(i);
}
System.out.println("sum:"+result);
executorService.shutdownNow();
}
}

/**
* 累加线程
* @author
* @time
*/
class AddCallable implements Callable<Long>{
private long begin ;
private long end ;

public AddCallable(long begin,long end){
this.begin = begin ;
this.end = end ;
}

@Override
public Long call() throws Exception {
long result = 0;
for(long i=begin;i<=end;i++){
result += i;
}
return result ;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值