实习-线程池

一、场景

  遍历esresult表,查找出当天需要执行节能指令的小区并执行指令。

  多线程并行执行,且降低线程切换的资源消耗——使用线程池。

二、线程池的核心线程数如何确定?

  1.IO密集型:应配置尽可能多的线程,因为IO操作不占用CPU,不能让它闲着,所以要多一点。一般为(2*处理器核数+1)

  2.CPU(计算)密集型:应配置尽可能小的线程,因为任务计算需要占用CPU,线程建多了也用不到CPU,只能傻等着。一般为(处理器核数+1)

  3.混合型:例如本项目,需要通过telnet指令连接基站、执行指令,请求响应时间较长,所以线程数需要多一点。且产品要求并发100,因此本项目核心线程数为100。

 三、代码

@Value("${omc.nep_ip:NE=JS_LTE_HW_OMC8}")
  @Value("******")
private String nep_ip; @Value("${omc.threadSize:100}")// 每threadSize条数据开启一条线程 private int threadSize; @Override public String receiveExec(CmdDTO cmdDTO) throws Exception { List<CmdVO> cmdVOs = cmdDTO.list; String actOrDea = cmdDTO.actOrDea; // 开始时间 long start = System.currentTimeMillis(); // 总数据条数 int dataSize = cmdVOs.size(); // 线程数 int threadNum = dataSize / threadSize + 1; // 定义标记,过滤threadNum为整数 boolean special = dataSize % threadSize == 0; // 创建一个线程池 ExecutorService exec = Executors.newFixedThreadPool(threadNum); // 定义一个任务集合 List<Callable<Integer>> tasks = new ArrayList<>(); Callable<Integer> task = null; List<CmdVO> cutList = null; // 确定每条线程的数据 for (int i = 0; i < threadNum; i++) { if (i == threadNum - 1) { if (special) { break; } cutList = cmdVOs.subList(threadSize * i, dataSize); } else { cutList = cmdVOs.subList(threadSize * i, threadSize * (i + 1)); } log.info("第" + (i + 1) + "组:" + cutList.toString()); final List<CmdVO> listStr = cutList; task = () -> { log.info(Thread.currentThread().getName() + "线程:" + listStr); exec(listStr, actOrDea); return 1; }; // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系 tasks.add(task); } List<Future<Integer>> results = exec.invokeAll(tasks); for (Future<Integer> future : results) { log.info(future.get() + ""); } // 关闭线程池 exec.shutdown(); log.info("线程任务执行结束"); log.info("执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒"); log.info("cmdExec入参:" + cmdVOs + ",长度:" + cmdVOs.size()); return "执行成功"; }

 

 

 

 

 

 

 

 

 

 

  

posted @ 2020-07-27 17:29  Qmillet  阅读(154)  评论(0编辑  收藏  举报