一、场景
遍历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 "执行成功";
}