问题点:
对于处理量较大的数据,需要用到线程池处理,来提高处理效率。而此时多线程会处理会产生对数据的重复处理。例如线程1取出id为0-100数据集合,正在处理中。此时线程2进来查询的可能是id40-140数据集合。这样对于40-60的数据就会重复处理。
解决方式:
CallerRunsPolicy —线程池拒绝策略
ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(4,
6,
2,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
new ThreadPoolExecutor.CallerRunsPolicy());
Phaser phaser =new Phaser(4);
Phaser phaser1 =new Phaser(4);
//查询全部
long count = XXX;
final Integer pageSize = Math.toIntExact(count / 20000);
for(int i=0;i<pageSize;i++){
//如果数量小,phasr减小,避免卡死
if(i+1>pageSize-(pageSize%4)){
phaser.arriveAndDeregister();
phaser1.arriveAndDeregister();
}
final int pageNum = i;
long startNum = pageNum*20000;
long endNum = 20000;
//查询分页
List<XXX> XXX = (startNum,endNum);
threadPoolExecutor.execute(()->{
//进入线程准备
phaser.arriveAndAwaitAdvance();
//等待4个线程都准备好在处理数据
for (XXX item : XXX) {
//对数据进行更新处理或新增处理
}
//线程到达
phaser1.arrive();
});
if((i+1)%4==0){
//所有线程都到达
phaser1.awaitAdvance(phaser1.getPhase());
}
}
}