多线程数据缓存集合达到一定数量或达到指定时间间隔后,进行消费清空缓存集合
需求大概如下:
从某平台(webservice)接收车记录数据,但是数据量是不确定的,有时候很多有时候又很少;
为了及时将接收到的数据转发出去,且尽可能减少转发的频次。于是设计一个接收数据的缓存集合,规定当集合的数据量达到一定数据量后,进行一次性消费;同时为了避免有时候接收的数据量很少,达不到转发的阈值,而出现少部分数据残留很久的情况,于是添加一个定时任务,定时将缓存集合中的数据全部转发出去。
下面看核心部分代码:
@Value("${each-file-size}") private int eachFileSize;//配置文件可配置,转发的阈值 private Executor queuePool = Executors.newFixedThreadPool(10); private AtomicReference<List<CarRecord>> atomicReference = new AtomicReference<>(new CopyOnWriteArrayList<>()); /** * 达到一定数量,或一定时间后,调用sendCarRecord进行批量操作 */ public void carRecord2Queue(CarRecord carRecord) { queuePool.execute(new Runnable() { @Override public void run() {
//下载图片,耗时操作 downloadImgWithRetry(carRecord); if (StringUtils.isNotBlank(carRecord.getSceneImageData())) { atomicReference.get().add(carRecord); if (atomicReference.get().size() >= eachFileSize) { sendCarRecord(); } } } }); } public void sendCarRecord() { if (atomicReference.get().size()==0){ return; } val carRecords = atomicReference.getAndSet(new CopyOnWriteArrayList<>()); if (carRecords.size() == 0) { return; } //写文件,消费缓存集合的数据 this.transmitByJoinType(carRecords); }
另外,还需要一个定时任务,调sendCarRecord()方法
@Async //@Scheduled(cron = "0/10 * * * * ?") @Scheduled(fixedDelay = 10 * 1000) //间隔10秒 public void check_car_record() { log.info("--------------定时检查 check_car_record---------------"); processService.sendCarRecord(); }