ListenableFuture顾名思义就是可以监听的Future,它是对java原生Future的扩展增强。我们知道Future表示一个异步计算任务,当任务完成时可以得到计算结果。如果我们希望一旦计算完成就拿到结果展示给用户或者做另外的计算,就必须使用另一个线程不断的查询计算状态。这样做,代码复杂,而且效率低下。使用ListenableFuture Guava帮我们检测Future是否完成了,如果完成就自动调用回调函数,这样可以减少并发程序的复杂度。
package com.mc.ThredPool;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Test;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
public class ThredPoolTest implements GuavaInteface {
private static ListeningExecutorService pool;
static {
//通过guava创建固定容量的线程池,用完需要调用shutdown方法关闭线程池。
pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
}
@Test
public void test() throws ExecutionException, InterruptedException {
Instant now = Instant.now();
Student st = new Student("付萌1", "女", 12, "高新");
Student st2 = new Student("付萌1", "女", 13, "高新");
Student st3 = new Student("付萌1", "女", 14, "高新");
Student st4 = new Student("付萌1", "女", 15, "高新");
Person p = new Person();
copyDto(p, st);
List result1 = new ArrayList<Student>();
List result2 = new ArrayList<Person>();
ListenableFuture<List> submit = pool.submit(() -> { //这里使用了lambda表达式,
for (int i = 0; i < 100000000; i++) { //也可以直接通过匿名内部类实现callable,runnable区别,一个有返回值,一个没有返回值
result1.add(st);
}
return result1;
});
ListenableFuture<List> submit1 = pool.submit(() -> {
for (int i = 0; i < 100000000; i++) {
result2.add(p);
}
return result2;
});
List list1 = submit.get();
List list = submit1.get();
pool.shutdown();//用完之后关闭线程池
Instant now1 = Instant.now();
System.out.println(list.size());
System.out.println(list1.size());
System.out.println("使用线程池耗时:"+Duration.between(now, now1).toMillis());
}
@Test
public void test1() throws ExecutionException, InterruptedException {
Instant now = Instant.now();
Student st = new Student("付萌1", "女", 12, "高新");
Student st2 = new Student("付萌1", "女", 13, "高新");
Student st3 = new Student("付萌1", "女", 14, "高新");
Student st4 = new Student("付萌1", "女", 15, "高新");
Person p = new Person();
copyDto(p, st);
List result1 = new ArrayList<Student>();
List result2 = new ArrayList<Person>();
for (int i = 0; i < 100000000; i++) {
result1.add(st);
}
for (int i = 0; i < 100000000; i++) {
result2.add(p);
}
Instant now1 = Instant.now();
System.out.println(result1.size());
System.out.println(result2.size());
System.out.println("不使用线程池耗时:"+Duration.between(now, now1).toMillis());
}
}
实际开发中,要是遇到多个查询(查询结果数据量很大的情况下)的话,可以考虑使用线程池,每个线程跑一个查询,增加效率,
1533196163(1).jpg
实际业务使用场景
ListenableFuture<List<WaybillServiceFeeVo>> futureTask = pool.submit(() -> {
List<WaybillServiceFeeVo> feeList = feeService.queryFeeAndRow2ColumnByWaybillNos(waybillNoArray);
return feeList;
});
ListenableFuture<List<ReceiveAddress>> addressFuture = pool.submit(new Callable<List<ReceiveAddress>>() {
@Override
public List<ReceiveAddress> call() throws Exception {
List<ReceiveAddress> addrList = addressService.queryAddressByWaybillNos(waybillNoArray);
return addrList;
}
});
ListenableFuture<List<WaybillApply>> applyFuture = pool.submit(new Callable<List<WaybillApply>>() {
@Override
public List<WaybillApply> call() throws Exception {
List<WaybillApply> applyList = waybillApplyService.queryApplyByNos(waybillNoArray);
return applyList;
}
});
try {
List<WaybillServiceFeeVo> feeList = futureTask.get();
if (feeList != null) {
batchCascadeWaybillFee(dtoList, feeList);
}
List<ReceiveAddress> addrList = addressFuture.get();
if (addrList != null) {
batchCascadeWaybillAddress(dtoList, addrList);
}
List<WaybillApply> applyList = applyFuture.get();
if (applyList != null) {
applyConvertWaybillDto(dtoList, applyList);
}
} catch (InterruptedException | ExecutionException e) {
throw new BusinessRuntimeException("等待失败");
}
return dtoList;
}
网友评论