在开发中有时经常用到异步多线程技术来快速高效完成某些任务,那常用的异步多线程技术参考如下:
1,建立一个用户自定义线程池
/**
* 自定义用户线程池,
* 注意:避免系统默认的线程池出现的性能问题
*/
@Bean("myExecutor")
public Executor myExecutor() {
ThreadPoolTaskExector executor = new ThreadPoolTaskExector();
//核心线程数
executor.setCorePoolSize(10);
//最大线程数
executor.setMaxPoolSize(20);
//队列中等待处理的最大的数目
executor.setQueueCapacity(200);
//线程空闲后的最大存活时间单位秒
executor.setKeepAliveSeconds(120);
//对拒绝task的处理策略
//rejection-policy:当pool已经达到max size的时候,如何处理新任务
//CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExector.CallerRunsPolicy());
//线程名称前缀
executor.setThreadNamePrefix("myExecutor-thread-pool-");
return executor;
}
2,各种场景的异步多线程参考如下注释和代码片段
/**
Java技术
1,异步多线程并行执行
注意:
myExecutor 为自定义的线程池;
runAsync 方法不支持返回值
supplyAsync 可以支持返回值
**/
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// 最后执行
// todo...
}
},myExecutor);
/**
2,异步多线程并行执行,某线程执行完,然后再执行后续如回调操作,
注意:
myExecutor 为自定义的线程池;
whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。
exceptionally:异常处理方法
*/
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).whenComplete((result, error) -> {
// 单线程内执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).exceptionally((throwable) -> {
// 异常时执行
// todo...
result "发生异常";
});
/**
3,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
注意:
myExecutor 为自定义的线程池;
handle 方法和 thenApply 方法处理方式基本一样;不同的是:
handle 是在任务完成后再执行,还可以处理异常的任务。
thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法
*/
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
// 第一次处理
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
}).exceptionally((throwable) -> {
// 异常时执行
// todo...
result "发生异常";
});
// handle 函数例子
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
// 第一次处理
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).handle((result, throwable) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
}).exceptionally((throwable) -> {
// 异常时执行
// todo...
result "发生异常";
});
/**
4,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
(1)两个线程任务连接,只要其中一个执行完成,就执行最后代码;
(2)两个线程任务连接,只有两个都执行完成,才执行最后代码;
注意:
myExecutor 为自定义的线程池;
runAfterEither 方法两个CompletionStage,任何一个完成了都会执行下一步的操作
runAfterBoth 方法两个CompletionStage,都完成了计算才会执行下一步的操作
*/
// 定义第一个 CompletableFuture 对象
String param01 = "...";
int param02 = "...";
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync((param01, param02) -> {
// 第一次处理
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
});
// 定义第二个 CompletableFuture 对象
String param03 = "...";
int param04 = "...";
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync((param03, param04) -> {
// 第一次处理
try {
String msg = xxService.fun01(param03, param04);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
});
String param05 = "..."; // 可从cf1获取值
String param06 = "..."; // 可从cf2获取值
// runAfterEither 方法任务其中之一完成就执行
// 线程任务一和二连接比较,最后只要其中有一个处理完成就执行该方法
cf1.runAfterEither(cf2, (param05, param06) -> {
System.out.println("上面其中有一个已经完成了");
//todo...
}).get();
// 线程任务一和二连接比较,最后只要其中有一个处理完成就执行该方法,另一写法
cf1.runAfterEither(cf2, new Runnable() {
@Override
public void run() {
System.out.println("上面其中有一个已经完成了");
}
}).get();
// runAfterBoth 方法两任务都完成才执行
// 线程任务一和二连接判断,最后只有两任务都处理完成就执行该方法
cf1.runAfterBoth(cf2, (param05, param06) -> {
System.out.println("上面两个任务都已经完成了");
//todo...
}).get();
// 线程任务一和二连接判断,最后只有两任务都处理完成就执行该方法,另一写法
cf1.runAfterBoth(cf2, new Runnable() {
@Override
public void run() {
System.out.println("上面两个任务都已经完成了");
}
}).get();
/**
5,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
在预期合理时间内未完成业务执行,当执行到complete则返回complete值
注意:
myExecutor 为自定义的线程池;
complete 线程任务执行完成则以该线程结果为准;如果在规定的时间内未执行完成时,
执行到complete,则返回complete的值
*/
String param01 = "...";
int param02 = "...";
public static void complete() throws Exception {
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync((param01, param02) -> {
// 第一次处理
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
});
// 主动休眠等待2秒
TimeUnit.SECONDS.sleep(2);
// cf1 执行完成则以该结果为准;
// 如果在规定的时间内前面未执行完成时执行complete,则返回complete值
cf1.complete("业务处理执行超时");
System.out.println("result: " + cf1.get());
}
/**
6,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
(1)多个线程任务连接,只要其中一个执行完成,就执行最后代码;
(2)多个线程任务连接,只有多个都执行完成,才执行最后代码;
注意:
myExecutor 为自定义的线程池;
allOf 在这里我们可以将对各future实例添加到allOf方法中,然后通过future的get()方法获取future的状态,
如果allOf里面的所有线程未执行完毕,主线程会阻塞,直到allOf里面的所有线程都执行完毕,主线程就会被唤醒;
anyOf 调用方法与allOf基本相同,区别在于anyOf是其中一个执行完成则往下执行,anyOf的get()方法返回最先执行完的Future;
*/
// 定义第一个 CompletableFuture 对象
String param01 = "...";
int param02 = "...";
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync((param01, param02) -> {
// 第一次处理
try {
String msg = xxService.fun01(param01, param02);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
});
// 定义第二个 CompletableFuture 对象
String param03 = "...";
int param04 = "...";
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync((param03, param04) -> {
// 第一次处理
try {
String msg = xxService.fun01(param03, param04);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
});
// 定义第三个 CompletableFuture 对象
String param05 = "...";
int param06 = "...";
CompletableFuture<String> cf3 = CompletableFuture.supplyAsync((param05, param06) -> {
// 第一次处理
try {
String msg = xxService.fun01(param05, param06);
return msg;
} catch(Exception e){
throw e;
} finally{
// todo...
}
},myExecutor).thenApply((result) -> {
// 第二次处理,依赖第一次执行结果
// 此处参数 result 其实就是上面返回的msg对象
String msg2 = xxService.fun02(result);
return msg2;
// todo...
}).whenComplete((result, error) -> {
// 单线程内前面执行完,然后再执行后续回调等操作
// 此处参数 result 其实就是上面返回的msg2对象
String msg3 = xxService.fun03(result);
return msg3;
// todo...
});
// 1,allOf 方法演示
System.out.println("三个线程任务执行完成状态:"
+ cf1.isDone()+" ," + cf2.isDone()+" ," + cf3.isDone());
// 通过主线程对其它三个线程任务进行连接
CompletableFuture<Void> allOfTask = CompletableFuture.allOf(cf1, cf2, cf3);
allOfTask.get();//这里会等待三个线程任务都执行完成,才执行后续代码
System.out.println("三个线程任务执行完成状态:"
+ cf1.isDone()+" ," + cf2.isDone()+" ," + cf3.isDone());
//2,anyOf 方法演示,此处与上面 allOf 方法不能同时使用
CompletableFuture<Object> anyOfTask = CompletableFuture.anyOf(cf1, cf2, cf3);
System.out.println("三个线程任务其中之一结果:" + anyOfTask.get());
System.out.println("三个线程任务执行完成状态:"
+ cf1.isDone()+" ," + cf2.isDone()+" ," + cf3.isDone());
// 综合例子,从海量产品数据中,每次分页取有限大小记录数量,
// 分批次进行多线程异步处理,所有线程任务都执行完成后才返回最后结果
public <String, String> handleProductAsync(List<Long> prodctIds){
if (null == prodctIds || prodctIds.size() < 1) {
return null;
}
//每页100条记录, 计算总页数
int pageSize = 100;
int totalNum = prodctIds.size();
int allPages = 0;
int modNum = totalNum % pageSize;
if (0 == modNum) {
allPages = totalNum % pageSize;
} else {
allPages = (totalNum - modNum) / pageSize + 1;
}
// 存放结果的map
private Map<String, String> retMap = new HashMap<String, String>();
//所有页数分批次进行异步多线程并行处理,
//建立的CompletableFuture对象放到一个数组中
CompletableFuture[] cfs = allPages.stream().map(
pageNum -> CompletableFuture.supplyAsync(() -> {
// todo...第一次处理
List<Long> tempIds = prodctIds.stream()
.skip((long)(pageNum - 1)*pageSize)
.limit(pageSize)
.collect(Collectors.toList());
Map<String, String> tempMap1 = xxxProductService.fun01(tempIds);
return tempMap1;
},myExecutor).thenApply((result01) -> {
// todo...第二次处理,依赖第一次执行结果
// 此处 result01 其实就是上面返回的tempMap1对象
Map<String, String> tempMap2 = xxxProductService.fun02(result01);
return tempMap2;
}).whenComplete((result02, error) -> {
// todo...单线程内前面执行完,然后再执行后续回调等操作
// 此处 result02 其实就是上面返回的tempMap2对象
String tempKey = "xxx";
String tempVal = xxxProductService.fun03(result02);
retMap.put(tempKey, tempVal);
})
).toArray(CompletableFuture[]::new);
//连接数组中所有线程任务,等待任务都执行完毕才返回结果
CompletableFuture.allOf(cfs).join();
return retMap;
}