java利用线程池带有返回值的方式,大体逻辑批量处理大量数据,启用线程池,处理完成后将所有的返回内容进行组装拼接
废话不多说开始看代码,重点敲黑板:
1.ThreadPoolExecutor 线程池创建
2.CountDownLatch 同步工具类,让主线程一直等待,直到子线程执行完后再执行
3.listret 用于接收多线程返回值
方式一
使用线程池
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(coresNumber * 2, coresNumber * 2 + 1, 1000, TimeUnit.MINUTES, new LinkedBlockingDeque<>());
/*创建List用来接收多线程返回的内容,泛型里面可以自定义,String或者对象亦或者其他类型*/
List
方法一得到的结果如下,使用线程池我这里是核数乘以2是核心线程16,最大17,所以这里最多是16个线程,而且他是无序的随机分配的
方式二
重点不用线程池使用@Async注解,但是策略得有所调整,大体逻辑比如你待处理的数据有100条,你可以将这个List按10条为一个新的List,循环这个集合,在调用的实际方法上加@Async注解,从而实现多线程加快循环也是可以的
@Async注意点,加了该注解的方法不能再同一个类,否则无效,其次有可能存在启动过程@Async UnsatisfiedDependencyException导致 SpringBoot 无法启动问题解决,我这里是在报错的类里有注入service或者mapper的注解上加了@Lazy注解就可以
// 将要发送的集合按10个一组进行重新组装
List> partition = Lists.partition(list, 10);
/*创建List用来接收多线程返回的内容,泛型里面可以自定义,String或者对象亦或者其他类型*/
List
方法二的执行结果,循环多少次就启动了多少个子线程,所以这里的想法是先将原生数组按自定义个进行分配,如有200个任务,分给20个人,每人10个大概就是这样的思路
我的完整代码仅供参考,里面很多类都是我自己业务用到的,大家可以借鉴
public Map initiateTargetPriceTask(PmpTargetPriceDTO pmpTargetPriceDTO) throws Exception {
String userName = SecurityUtils.getUsername();
Map map = new HashMap();
List list = Arrays.asList(pmpTargetPriceDTO.getIds());
// 将要发送的集合按10个一组进行重新组装
List> partition = Lists.partition(list, 10);
// 创建一个线程池
// 获取CPU核数
int coresNumber = Runtime.getRuntime().availableProcessors();
System.out.println("获取CPU核数:" + coresNumber);
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(coresNumber * 2, coresNumber * 2 + 1, 1000, TimeUnit.MINUTES, new LinkedBlockingDeque<>());
// 获取任务发起类型字段
String initiateTaskType = pmpTargetPriceDTO.getInitiateTaskType();
/*创建List用来接收多线程返回的内容,泛型里面可以自定义,String或者对象亦或者其他类型*/
List
总结方式一和方式二都能解决加快任务处理,处理时间都差不读多,大家可以挑选自己适合的方式,如有更好的方式或不对的点请指正,欢迎大家沟通交流,共同成长进步