/**
* 多线程处理集合
* @param list
* @return
*/
public List<PushOrganize> setDataByDmsOrgInfo(List<DmsOrgInfo> list) throws InterruptedException {
List<PushOrganize> pushOrganizeList=new ArrayList<>();
Map<String,List<PushOrganize>> pushOrganizeMap=new HashMap<>();
// 开始时间
long start = System.currentTimeMillis();
/*动态线程数方式
// 每500条数据开启一条线程
int threadSize = 500;
// 总数据条数
int dataSize = list.size();
// 线程数,动态生成
int threadNum = dataSize / threadSize + 1;
*/
//固定线程数方式
// 线程数
int threadNum = 6;
// 总数据条数
int dataSize = list.size();
// 每一条线程处理多少条数据
int threadSize = dataSize / (threadNum - 1);
// 定义标记,过滤threadNum为整数
boolean special = dataSize % threadSize == 0;
// 创建一个线程池
ExecutorService exec = Executors.newFixedThreadPool(threadNum);
// 定义一个任务集合
List<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>();
Callable<Integer> task = null;
List<DmsOrgInfo> cutList = null;
// 确定每条线程的数据
for (int i = 0; i < threadNum; i++) {
if (i == threadNum - 1) {
if (special) {
break;
}
cutList = list.subList(threadSize * i, dataSize);
} else {
cutList = list.subList(threadSize * i, threadSize * (i + 1));
}
final List<DmsOrgInfo> listStr = cutList;
task = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
List<PushOrganize> pushOrganizes=new ArrayList<>();
pushOrganizeMap.put(Thread.currentThread().getName(), pushOrganizes);
//业务逻辑,循环处理分段后的list
for (DmsOrgInfo dmsOrgInfo: listStr) {
PushOrganize pushOrganize=new PushOrganize();
//组织名
pushOrganize.setOrganizationName(dmsOrgInfo.getOrgName() == null ? "" : dmsOrgInfo.getOrgName());
//是否启用
pushOrganize.setEnabled(true);
//组织机构的唯一id
pushOrganize.setExternalId(dmsOrgInfo.getCompanyId().toString() + "-" + dmsOrgInfo.getOrgId().toString());
//父级组织机构的id
pushOrganize.setParentExternalId(dmsOrgInfo.getParentOrgId() == null ? "" : dmsOrgInfo.getParentOrgId().toString());
//放入对应的集合
System.out.println(Thread.currentThread().getName());
//补充:这样是不行的,无法真正的保证线程安全,线程安全主要有三个要素:
1.可见性 2.有序性 3.原子性
共享变量保证线程安全的正确解决方式:
使用集合 vector 、concurrenthashmap、synchronized、lock、cas、atomic相关类等,
具体配合视频并发编程篇章学习 --源码地址java.until.concurrent author:doug lea
pushOrganizeMap.get(Thread.currentThread().getName()).add(pushOrganize);
}
return 1;
}
};
// 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
tasks.add(task);
}
exec.invokeAll(tasks);
for(List<PushOrganize> organizeList:pushOrganizeMap.values()) {
pushOrganizeList.addAll(organizeList);
}
// 关闭线程池
exec.shutdown();
System.out.println("线程任务执行结束");
System.out.println("执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
return pushOrganizeList;
}