瀏覽代碼

解决线程不安全问题

李进 2 年之前
父節點
當前提交
a887f9af26
共有 1 個文件被更改,包括 62 次插入46 次删除
  1. 62 46
      device-api-service/src/main/java/com/xy/service/DeviceDataServiceImpl.java

+ 62 - 46
device-api-service/src/main/java/com/xy/service/DeviceDataServiceImpl.java

@@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.xy.annotation.Lock;
 import com.xy.collections.list.JArrayList;
 import com.xy.collections.map.JConcurrentHashMap;
 import com.xy.collections.map.JHashMap;
@@ -21,6 +20,7 @@ import com.xy.utils.enums.DictSonEnum;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -141,51 +141,8 @@ public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceD
 
     @ApiOperation("添加/累加")
     @PostMapping("saveOrAccum")
-    @Lock(value = "saveOrAccum.deviceId", prefix = "data_save_accum_")
-    public R saveOrAccum(DeviceDataDto.SaveOrAccum saveOrAccum) {
-        LocalDateTime now = LocalDateTime.now();
-        String yyyyMMdd = DataTime.toString(now, "yyyyMMdd");
-        //获取字典
-        Map<String, SysDictRedis> map = SysDictUtils.get(DictEnum.DEVICE_DATA_TYPE.getKey());
-        JMap<String, Integer> jMap = new JHashMap<>(map.size());
-        map.forEach((type, sysDictRedis) -> {
-            Integer dateValue = Integer.valueOf(yyyyMMdd.substring(0, Integer.valueOf(sysDictRedis.getValue())));
-            jMap.put(type, dateValue);
-        });
-        //查询已存在数据
-        List<DeviceData> list = list(new LambdaQueryWrapper<DeviceData>()
-                .eq(DeviceData::getDeviceId, saveOrAccum.getDeviceId())
-                .in(DeviceData::getDateValue, jMap.toList().value())
-        );
-        JMap<String, DeviceData> typeMaps = new JArrayList<>(list).toMap(DeviceData::getType).cover();
-        //新增或修改的多线程桶map集合
-        JMap<String, DeviceData> dbMaps = new JConcurrentHashMap<>(map.size());
-        //封装新增或修改对象
-        jMap.forEach((type, dateValue) -> {
-            DeviceData deviceData = typeMaps.get(type);
-            //添加
-            if (deviceData == null) {
-                DeviceData saveOrUpdateInfo = copy(DeviceData.class, saveOrAccum)
-                        .setCreateTime(now)
-                        .setUpdateTime(now)
-                        .setType(type)
-                        .setDateValue(dateValue);
-                dbMaps.put(type, saveOrUpdateInfo);
-                return;
-            }
-            //累加
-            DeviceData updateDeviceData = new DeviceData().setId(deviceData.getId()).setUpdateTime(now)
-                    .setSalesMoney(saveOrAccum.getSalesMoney() != null ? saveOrAccum.getSalesMoney() + deviceData.getSalesMoney() : null)
-                    .setSalesCount(saveOrAccum.getSalesCount() != null ? saveOrAccum.getSalesCount() + deviceData.getSalesCount() : null)
-                    .setGoodsCount(saveOrAccum.getGoodsCount() != null ? saveOrAccum.getGoodsCount() + deviceData.getGoodsCount() : null)
-                    .setRefundMoney(saveOrAccum.getRefundMoney() != null ? saveOrAccum.getRefundMoney() + deviceData.getRefundMoney() : null)
-                    .setRefundCount(saveOrAccum.getRefundCount() != null ? saveOrAccum.getRefundCount() + deviceData.getRefundCount() : null)
-                    .setZeroCount(saveOrAccum.getZeroCount() != null ? saveOrAccum.getZeroCount() + deviceData.getZeroCount() : null)
-                    .setDeviceFaultCount(saveOrAccum.getDeviceFaultCount() != null ? saveOrAccum.getDeviceFaultCount() + deviceData.getDeviceFaultCount() : null);
-            dbMaps.put(type, updateDeviceData);
-        });
-        saveOrUpdateBatch(dbMaps.toList().value());
-        return R.ok();
+    public R saveOrAccum(@RequestBody DeviceDataDto.SaveOrAccum saveOrAccum) {
+        return new SaveOrAccum().saveOrAccum(this, saveOrAccum);
     }
 
     /**
@@ -328,5 +285,64 @@ public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceD
         return copy(DeviceDataDto.Vo.class, list);
     }
 
+    public static class SaveOrAccum {
 
+        public R saveOrAccum(DeviceDataServiceImpl deviceDataService, DeviceDataDto.SaveOrAccum saveOrAccum) {
+            return new LockUtils()
+                    .name("saveOrAccum.deviceId")
+                    .prefix("data_save_accum_")
+                    .build(SaveOrAccum.class)
+                    .exec(deviceDataService, saveOrAccum);
+        }
+
+        @SneakyThrows
+        public R exec(DeviceDataServiceImpl deviceDataService, DeviceDataDto.SaveOrAccum saveOrAccum) {
+            if (saveOrAccum.getSalesCount() == 1) {
+                Thread.sleep(5000);
+            }
+            LocalDateTime now = LocalDateTime.now();
+            String yyyyMMdd = DataTime.toString(now, "yyyyMMdd");
+            //获取字典
+            Map<String, SysDictRedis> map = SysDictUtils.get(DictEnum.DEVICE_DATA_TYPE.getKey());
+            JMap<String, Integer> jMap = new JHashMap<>(map.size());
+            map.forEach((type, sysDictRedis) -> {
+                Integer dateValue = Integer.valueOf(yyyyMMdd.substring(0, Integer.valueOf(sysDictRedis.getValue())));
+                jMap.put(type, dateValue);
+            });
+            //查询已存在数据
+            List<DeviceData> list = deviceDataService.list(new LambdaQueryWrapper<DeviceData>()
+                    .eq(DeviceData::getDeviceId, saveOrAccum.getDeviceId())
+                    .in(DeviceData::getDateValue, jMap.toList().value())
+            );
+            JMap<String, DeviceData> typeMaps = new JArrayList<>(list).toMap(DeviceData::getType).cover();
+            //新增或修改的多线程桶map集合
+            JMap<String, DeviceData> dbMaps = new JConcurrentHashMap<>(map.size());
+            //封装新增或修改对象
+            jMap.forEach((type, dateValue) -> {
+                DeviceData deviceData = typeMaps.get(type);
+                //添加
+                if (deviceData == null) {
+                    DeviceData saveOrUpdateInfo = copy(DeviceData.class, saveOrAccum)
+                            .setCreateTime(now)
+                            .setUpdateTime(now)
+                            .setType(type)
+                            .setDateValue(dateValue);
+                    dbMaps.put(type, saveOrUpdateInfo);
+                    return;
+                }
+                //累加
+                DeviceData updateDeviceData = new DeviceData().setId(deviceData.getId()).setUpdateTime(now)
+                        .setSalesMoney(saveOrAccum.getSalesMoney() != null ? saveOrAccum.getSalesMoney() + deviceData.getSalesMoney() : null)
+                        .setSalesCount(saveOrAccum.getSalesCount() != null ? saveOrAccum.getSalesCount() + deviceData.getSalesCount() : null)
+                        .setGoodsCount(saveOrAccum.getGoodsCount() != null ? saveOrAccum.getGoodsCount() + deviceData.getGoodsCount() : null)
+                        .setRefundMoney(saveOrAccum.getRefundMoney() != null ? saveOrAccum.getRefundMoney() + deviceData.getRefundMoney() : null)
+                        .setRefundCount(saveOrAccum.getRefundCount() != null ? saveOrAccum.getRefundCount() + deviceData.getRefundCount() : null)
+                        .setZeroCount(saveOrAccum.getZeroCount() != null ? saveOrAccum.getZeroCount() + deviceData.getZeroCount() : null)
+                        .setDeviceFaultCount(saveOrAccum.getDeviceFaultCount() != null ? saveOrAccum.getDeviceFaultCount() + deviceData.getDeviceFaultCount() : null);
+                dbMaps.put(type, updateDeviceData);
+            });
+            deviceDataService.saveOrUpdateBatch(dbMaps.toList().value());
+            return R.ok();
+        }
+    }
 }