防止并发问题
Posted realworld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了防止并发问题相关的知识,希望对你有一定的参考价值。
“同步设备”(无论是手工同步,还是自动同步)操作,是一个单一排它性操作,也就是无论点击多少次,还是当前同步时长太长,同一时间内只能有一个同步操作。
因此,我们需要添加代码来防止并发的同步操作,包括:
1)点击手工同步时,如果当前已经有同步任务,则需要提示:“系统正在同步中,请完成后再操作”
2)自动同步时,如果当前有同步任务(是手工,还是上一次未完成),则放弃本次同步操作,让原来的同步任务继续进行
防止并发的同步操作应该怎么做?
public class SyncDeviceWorkerManager { private static ScheduledFuture<?> workerFuture; /** * 如果任务正在运行当中,则必须要等到任务完成,才会调度下一轮 */ private static volatile boolean commandRunning = false; private static SyncDeviceWorker command = null; /** * 一个任务的任务池 */ private static ScheduledExecutorService syncService = Executors.newScheduledThreadPool(2); /** * 初始化 * * @param sync 是否立即启动同步工作。 sync=true 表示启动任务, false表示不启动任务 */ public static void initSyncWorkerManager(boolean sync){ ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); //任务取消后,将被从队列中移除 executor.setRemoveOnCancelPolicy(true); //固定设置后,不希望被修改 syncService = Executors.unconfigurableScheduledExecutorService(executor); if(sync){ scheduledSyncDevice(null); } } /** * 同步设备调度 * * @param deviceRefreshConfig */ public static BooleanResult scheduledSyncDevice(DeviceRefreshConfig deviceRefreshConfig) { try{ DeviceRefreshConfig oldConfig = DeviceRefreshConfigManager.getDeviceRefreshConfig(); if(deviceRefreshConfig == null || !deviceRefreshConfig.equals(oldConfig)){ if(workerFuture != null){ workerFuture.cancel(false); } //重新创建任务 command = new SyncDeviceWorker(deviceRefreshConfig==null?oldConfig:deviceRefreshConfig); workerFuture = syncService.scheduleWithFixedDelay( command, 0L, command.getPeriod(), command.getTimeUnit()); } return BooleanResult.SUCCESS; }catch(Exception e){ LogManager.getInstance() .logSyncUError("[CCM同步]==> 重新调度同步任务失败,异常:", e); return BooleanResult.ofException(e); } }
手动同步
private boolean syncDevice = false; @Post("/sync") public BooleanResult sync(){ LogManager.getInstance().info("[Post /devices/sync]==> 同步设备信息开始..."); if(!syncDevice){ syncDevice = true; try{ return SyncDeviceService.syncDeviceFromCCM(); }finally{ syncDevice = false; } } return BooleanResult.SUCCESS; }
定时同步 SyncDeviceWorker.java @Override public void run() { try{ syncDevices(); }finally{ //在任务中需要手工释放数据库连接 DataConnectionManager.returnConnection(); } } /** * 同步设备 */ private void syncDevices() { LogManager.getInstance() .logSyncUInfo("开始同步设备信息"); SyncDeviceService.syncDeviceFromCCM() .done(success->{ LogManager.getInstance() .logSyncUInfo("本次同步设备信息成功"); }) .fail(err->{ LogManager.getInstance() .error("[同步 CCM 设备]==> 设备同步失败,错误:", err); }); }
以上是关于防止并发问题的主要内容,如果未能解决你的问题,请参考以下文章