防止并发问题

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);
                         });
    }

 




以上是关于防止并发问题的主要内容,如果未能解决你的问题,请参考以下文章

使用底部导航栏防止片段刷新

使用导航从一个片段导航到另一个片段后,防止后按工作

防止导航到同一个片段

在后台堆栈中多次防止相同的片段

如何防止在背面片段导航上再次设置视图模型

golang goroutine例子[golang并发代码片段]