问题描述
项目中存在如下伪代码:
其中customThreadPool
变量是项目自定义的线程池,fileBeatInstanceDTO
变量是线程池外部创建的一个对象。
最后issueOperator.operateWhenFirstDeploy
方法接收fileBeatInstanceDTO
参数。
FileBeatInstanceDTO fileBeatInstanceDTO = new FileBeatInstanceDTO();
......
......
//赋值
fileBeatInstanceDTO.setHosts(hostsMap.get(hosts.getHostId()));
fileBeatInstanceDTO.setCollectInstanceMappingId(finalCollectInstanceMappingId);
......
......
//自定义的线程池
customThreadPool.execute(()->{
try {
......
......
//接收fileBeatInstanceDTO参数
issueOperator.operateWhenFirstDeploy(fileBeatInstanceDTO);
} catch (Exception e) {
log.error("", e);
}
});
当customThreadPool
提交多个任务时,issueOperator.operateWhenFirstDeploy
方法运行的结果,偶尔会与预期不一致。
问题分析
在issueOperator.operateWhenFirstDeploy
方法内部打印fileBeatInstanceDTO
变量的值,发现有多个任务时,偶尔存在多个任务的fileBeatInstanceDTO
里属性一致的情况。
但实际业务需要的是,不同任务的fileBeatInstanceDTO
属性不一样。
分析
issueOperator.operateWhenFirstDeploy
方法接收的fileBeatInstanceDTO
是同一个引用。
当A任务的issueOperator.operateWhenFirstDeploy
方法在运行时,B任务可能会通过如下代码修改这个引用,导致A任务预期的值错误
fileBeatInstanceDTO.setHosts(hostsMap.get(hosts.getHostId()));
fileBeatInstanceDTO.setCollectInstanceMappingId(finalCollectInstanceMappingId);
解决
将fileBeatInstanceDTO
定义在线程池内部
......
......
//自定义的线程池
customThreadPool.execute(()->{
FileBeatInstanceDTO fileBeatInstanceDTO = new FileBeatInstanceDTO();
......
......
//赋值
fileBeatInstanceDTO.setHosts(hostsMap.get(hosts.getHostId()));
fileBeatInstanceDTO.setCollectInstanceMappingId(finalCollectInstanceMappingId);
try {
......
......
//接收fileBeatInstanceDTO参数
issueOperator.operateWhenFirstDeploy(fileBeatInstanceDTO);
} catch (Exception e) {
log.error("", e);
}
});