一. 作用:提高业务代码编写效率,不用将精力浪费在如何将数据切断分配给工作线程。
二. 适用范围:使用多线程并发处理大批量任务数据时。
三. 注意:① 当线程中需要Bean对象时,可以使用ApplicationContext对象进行Bean对象的获取。
② 具体线程并发数请根据实际Cpu内核数进行确认
③ 基于spring提供的线程池,如果需要可以根据实际情况进行修改
上代码:
package com.example.demo;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
/**
* 提高开发效率,这里设置多线程处理策略
*/
public class SimpleThreadExecute<T> {
/**
* 待执行的数据集合
*/
private ArrayList<T> list;
/**
* 执行任务的线程池
*/
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
/**
* 当前任务最大并发线程数
*/
private int loadThread;
/**
* 将数据集合交于指定线程处理
*/
public SimpleThreadExecute(ArrayList<T> list, ThreadPoolTaskExecutor pool,int loadThread){
this.list = list;
this.loadThread = loadThread;
this.threadPoolTaskExecutor = pool;
}
/**
* 执行任务的方法
*/
public void Execute(Class Thread){
//程序计时
long startTime = System.currentTimeMillis();
//健壮性判断
if (null!=list && list.size()>0 && null!=threadPoolTaskExecutor && loadThread>0){
//计算每组数据量
int load = list.size()/loadThread;
System.out.println("数据量:"+list.size()+",每条线程执行的数量"+load);
CountDownLatch countDownLatch = new CountDownLatch(loadThread);
try{
//数据分组,启动线程
for (int i=0;i<loadThread;i++){
//最后一条线程处理所有任务
if (i==(loadThread-1)){
List<T> ts = list.subList(i * load, list.size());
threadPoolTaskExecutor.submit((Callable<? extends Object>) Thread.getConstructor(List.class,String.class,CountDownLatch.class).newInstance(ts,"线程"+i,countDownLatch));
}else {
List<T> ts = list.subList(i * load, i * load + load);
threadPoolTaskExecutor.submit((Callable<? extends Object>) Thread.getConstructor(List.class,String.class,CountDownLatch.class).newInstance(ts,"线程"+i,countDownLatch));
}
}
//等待所有线程执行完毕
countDownLatch.await();
}catch (Exception e){
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("本次方法耗时:"+(endTime-startTime));
}
}
}
任务线程创建格式
这里需要注意任务线程的构造方法,参数的数量及顺序是与工具类中一致的
package com.example.Thread;
import com.example.Dto.Animal;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
public class workThread implements Callable {
/**
* 需要处理的数据集合
*/
private List<Animal> list;
/**
* 程序计数器
*/
private CountDownLatch countDownLatch;
/**
* 线程名
*/
private String threadName;
public workThread (List<Animal> list, String threadName, CountDownLatch countDownLatch){
this.list=list;
this.threadName=threadName;
this.countDownLatch=countDownLatch;
}
@Override
public Object call() throws Exception {
for (int i=0;i<list.size();i++){
System.out.println(threadName+":"+list.get(i).getIndex());
}
countDownLatch.countDown();
return null;
}
}
如果希望在线程中使用Bean对象,那么可以基于ApplicationContext 的形式获取(例如数据查询写入以及关联其他业务代码等)
工具类初始化以及调用过程
SimpleThreadExecute<Animal> threadPoolTaskExecutor =
new SimpleThreadExecute<>(animals, (ThreadPoolTaskExecutor) StringUtil.getBean("threadPoolTaskExecutor"), 8);
threadPoolTaskExecutor.Execute(workThread.class);
获取Bean对象的工具类
package com.example.config;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class StringUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("加载上下文对象");
context = applicationContext;
}
/**
* 获取上下文对象
* @return
*/
public static ApplicationContext getApplicationContext(){
return context;
}
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
public static <T> T getBean(Class<T> requiredType) throws BeansException{
return getApplicationContext().getBean(requiredType);
}
}
如果各位大佬有修改意见,请留言支持一下哈,有帮助定期优化。感谢。