多线程处理数据
/** * 多线程处理集合 * @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; }