借鉴网址:传送点
1. Future的应用场景
在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。
Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。
举个例子:比如去吃早点时,点了包子和凉菜,包子需要等3分钟,凉菜只需1分钟,如果是串行的一个执行,在吃上早点的时候需要等待4分钟,但是因为你在等包子的时候,可以同时准备凉菜,所以在准备凉菜的过程中,可以同时准备包子,这样只需要等待3分钟。那Future这种模式就是后面这种执行模式。
2. Future的主要方法:
get()方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕
get(long timeout,TimeUnit unit)做多等待timeout的时间就会返回结果
cancel(boolean mayInterruptIfRunning)方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false.
isDone()方法判断当前方法是否完成
isCancel()方法判断当前方法是否取消
3.对比示例
我先来写一种利用使用线程池,但是要得到最后结果的一种比较low的写法来衬托使用 Future类的好用之处和特点
第一种写法:
// 测试线程池使用和future使用
@Test
public void testThread(){
//创建一个固定线程数的线程池
ExecutorService executorService=Executors.newFixedThreadPool(2);
//开启线程
executorService.execute(new Runnable() {
@Override
public void run() {
try{
System.out.println("开启线程一并执行");
Thread.sleep(2000);
System.out.println("线程一执行完毕");
}catch (Exception e){
e.printStackTrace();
}
}
});
//开启线程
executorService.execute(new Runnable() {
@Override
public void run() {
try{
System.out.println("开启线程二并执行");
Thread.sleep(1000);
System.out.println("线程二执行完毕");
}catch (Exception e){
e.printStackTrace();
}
}
});
executorService.shutdown();
while(true) {
if (executorService.isTerminated()) {
System.out.println("所有的子线程都结束了!");
break;
}
}
}
结果:
第二种:利用Future类
// 测试线程池使用和future使用
@Test
public void testThreadUseFuture() {
Integer one=null;
Integer two=null;
//创建一个固定线程数的线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
//自定义内部类实现Callable 执行实际运行内容
OneThread oneThread=new OneThread();
//开启线程
Future<Integer> future1=executorService.submit(oneThread);
//自定义内部类实现Callable 执行实际运行内容
TwoThread twoThread=new TwoThread();
//开启线程
Future<Integer> future2=executorService.submit(twoThread);
try{
one= future1.get();
two=future2.get();
}catch (Exception e){
e.printStackTrace();
}
Integer sum=one+two;
System.out.println(sum);
}
class OneThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 1;
}
}
class TwoThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return 2;
}
}
结果:
4.结果
Future的get方法在工作还没有结束,则会阻塞线程,直到任务执行完毕这样我们在一个方法中启动多线程时就可一在主进程拿到线程执行后的完成的结果。使用future时,线程需要使用executorService.submit方法 这个方法需要自定义内部类或者自定义类 在自定义内部类中写执行语句或者代码逻辑。在视觉上是起到减少使用execute实现Runnable方法的代码长度。
Future可以定义泛型来接受不同的返回值。
5.实际应用包含参数传递
@Override
public Result getNewCreativeList(SemCreativeParam param, String userId, String userName, String serviceLine) {
long startTime = System.currentTimeMillis();
param = (SemCreativeParam) commonService.formatParamDate(param);
StringBuffer group = new StringBuffer("creative_id,fr");
// invokeGroup(group, param.getDate_type());
param.setGroup(group.toString());
invokeParam(param,userId, userName,serviceLine);
String orderAccessFields = reportFieldsService.orderAccessFields(param.getAccess_service_line(),JSON.toJSONString(param),param.getAccess_fields(),"4");
param.setAccess_fields(orderAccessFields);
param.setAccessType(AccessTypeEnum.LIST.name());
String stringOrgFileds = param.getAccess_fields();
JSONObject result = null;
//================================非阻塞式调用
ExecutorService executorService = Executors.newFixedThreadPool(4);
ListTask list1 = new ListTask(param);
Future<JSONObject> list1Result = executorService.submit(list1);
SumTask sum1Task = new SumTask(param);
Future<Map<String, Object>> sum1Result = executorService.submit(sum1Task);
Future<Map<String, Object>> sum2Result = null;
//对比数据进行接口调用
if (param.getContrast_start_date()!= null && param.getContrast_end_date() != null){
param.setStart_date(param.getContrast_start_date());
param.setEnd_date( param.getContrast_end_date());
//包装返回
param.setPage(null);
param.setSize(null);
SumTask sum2Task = new SumTask(param);
sum2Result = executorService.submit(sum2Task);
}
try{
//======================第一次列表 汇总 与 第二次汇总结果返回================
result = list1Result.get();
Map<String, Object> sum1Map = sum1Result.get();
Map<String, Object> sum2Map = null;
if (param.getContrast_start_date()!= null && param.getContrast_end_date() != null){
sum2Map = sum2Result.get();
}
Integer total = result.getInteger("total");
Map<String,Object> creativeTitleMap = new LinkedHashMap<>();
creativeTitleMap.put("label","创意");
creativeTitleMap.put("prop","creative_title");
List<String> listUn = SemCreativeFiledsFilter.unShowFiledList;
listUn.add("fr_name");
List<Map<String, Object>> header = SemFieldHeaderUtil.getHeader(orderAccessFields,listUn);
header.add(1,creativeTitleMap);
result.put("header",header);
//=====================预处理二次并调用第二次列表===============
if (null != sum2Result){
String normalDate = DateUtil.getChDateSection(param.getDate_type(), param.getStart_date(), param.getEnd_date());
String contrastDate = DateUtil.getChDateSection(param.getDate_type(), param.getContrast_start_date(), param.getContrast_end_date());
List<String> creativeIds = new ArrayList<>();
prossessCreativeIds(result, creativeIds);
param.setCreative_ids(StringUtils.join(creativeIds,","));
param.setAccess_fields(stringOrgFileds);
ListTask list2Task = new ListTask(param);
Future<JSONObject> list2TastResult = executorService.submit(list2Task);
JSONObject result2 = list2TastResult.get();
List<Map<String, Object>> comList = prossessComList(result.getJSONArray("list"), result2.getJSONArray("list"), normalDate, contrastDate);
Map<String, Object> sumJsonObject = prossessComSum(sum1Map, sum2Map, normalDate, contrastDate);
result = new JSONObject();
comList.add(0,sumJsonObject);
result.put("list",comList);
result.put("total", total);
header = SemFieldHeaderUtil.getCreativeComHeader(orderAccessFields);
header.add(1,creativeTitleMap);
result.put("header",header);
return Result.success(result);
}
JSONArray list = result.getJSONArray("list");
list.add(0, sum1Map);
result.put("list",list);
long end = System.currentTimeMillis();
System.out.println("总耗时:==========" +(end-startTime));
return Result.success(result);
}catch (Exception e){
throw new InvalidParamException("error from databus or thread Error:"+e.getMessage());
}finally {
executorService.shutdown();
}
}
//可自定义修改接受类型和返回值类型
class ListTask implements Callable<JSONObject> {
SemCreativeParam param ;
public ListTask(SemCreativeParam param) {
this.param = param;
}
@Override
public JSONObject call() throws Exception {
return queryList(param);//具体执行代码
}
}
//可自定义修改接受类型和返回值类型
class SumTask implements Callable< Map<String,Object>>{
SemCreativeParam param ;
public SumTask(SemCreativeParam param) {
this.param = param;
}
@Override
public Map<String,Object> call() throws Exception {
return querySummary(param);//具体执行代码
}
}
结束
感谢观看!