Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedata/becleanitem/service/ClassifyBasketManagerImpl.java =================================================================== diff -u -r40704 -r40785 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedata/becleanitem/service/ClassifyBasketManagerImpl.java (.../ClassifyBasketManagerImpl.java) (revision 40704) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedata/becleanitem/service/ClassifyBasketManagerImpl.java (.../ClassifyBasketManagerImpl.java) (revision 40785) @@ -404,36 +404,15 @@ if(StringUtils.isBlank(barcode)){ return null; } - String sql = String.format("select po from %s po " - + "where po.containerBarcode = '%s' " - + "and po.classifyBasketStatus = 0 " - + "and po.id not in (select cb.id from WashAndDisinfectRecord wr join wr.classifyBaskets cb) " - + "order by po.recyclingTime desc" - , ClassifyBasket.class.getSimpleName(), - barcode); + + String sql = "SELECT po FROM ClassifyBasket po " + + "LEFT JOIN FETCH po.washAndDisinfectRecords wr " + + "WHERE po.containerBarcode = '" + barcode + + "' AND po.classifyBasketStatus = 0 " + + "AND wr.id IS NULL " + // 没有清洗记录的篮筐 + "ORDER BY po.recyclingTime DESC"; logger.debug("获取还未清洗且里面的物品未被全部终止的篮筐:"+sql); - List list = null; - int retryCount = 60; // 最大重试次数 - boolean success = false; - while (retryCount > 0 && !success) { - try { - list = objectDao.findByHql(sql); - success = true; // 如果成功,退出循环 - } catch (InvalidDataAccessResourceUsageException e) { - retryCount--; - if (retryCount == 0) { - throw new RuntimeException("获取篮筐异常", e); - } - // 等待一段时间后重试 - try { - Thread.sleep(1000); // 等待 1 秒 - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException("获取篮筐异常", ie); - } - - } - } + List list = objectDao.findByHql(sql, 1,1); if(CollectionUtils.isEmpty(list)){ return null; } Index: ssts-recyclingrecord/src/main/java/com/forgon/disinfectsystem/recyclingrecord/service/RecyclingRecordManagerImpl.java =================================================================== diff -u -r40774 -r40785 --- ssts-recyclingrecord/src/main/java/com/forgon/disinfectsystem/recyclingrecord/service/RecyclingRecordManagerImpl.java (.../RecyclingRecordManagerImpl.java) (revision 40774) +++ ssts-recyclingrecord/src/main/java/com/forgon/disinfectsystem/recyclingrecord/service/RecyclingRecordManagerImpl.java (.../RecyclingRecordManagerImpl.java) (revision 40785) @@ -11,6 +11,7 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -1265,42 +1266,33 @@ } return basket; } - /** - * 获取篮筐实例 获取不到就新建 - * @param washClassifyType 清洗篮筐类型 - * @param containerBarcode 容器条码 - * @param containerName 容器名称 - * @return - */ - private synchronized ClassifyBasket getOrCreateClassifyBasket(String washClassifyType, String containerBarcode, String containerName) { - ClassifyBasket classifyBasket = classifyBasketManager.getFirstUnWashedAndTousseItemUnEndBasket(containerBarcode); - if (classifyBasket == null && !dbConnection.isTiDB()) {//TiDB存在一些问题 比如获取不到NewClassifyBasketThread中创建的实例 比如保存时发生唯一约束错误 - classifyBasket = new ClassifyBasket(); - NewClassifyBasketThread newClassifyBasketThread = new NewClassifyBasketThread(classifyBasket, objectDao, washClassifyType, containerBarcode, containerName); - startAndWaitForThread(newClassifyBasketThread); - if(!DatabaseUtil.isPoIdValid(classifyBasket.getId())){ - classifyBasket = classifyBasketManager.getFirstUnWashedAndTousseItemUnEndBasket(containerBarcode); + + private final ConcurrentHashMap barcodeLocks = new ConcurrentHashMap<>(); + + /** + * 获取篮筐实例 获取不到就新建(条码级别锁) + */ + private ClassifyBasket getOrCreateClassifyBasket(String washClassifyType, String containerBarcode, String containerName) { + Object lock = barcodeLocks.computeIfAbsent(containerBarcode, k -> new Object()); + + synchronized (lock) { + try { + ClassifyBasket classifyBasket = classifyBasketManager.getFirstUnWashedAndTousseItemUnEndBasket(containerBarcode); + if (classifyBasket == null) { + classifyBasket = new ClassifyBasket(); + classifyBasket.setContainerBarcode(containerBarcode); + classifyBasket.setContainerName(containerName); + classifyBasket.setWashClassifyType(washClassifyType); + objectDao.save(classifyBasket); + } + return classifyBasket; + } finally { + if (barcodeLocks.get(containerBarcode) == lock) { + barcodeLocks.remove(containerBarcode, lock); + } } - if (!DatabaseUtil.isPoIdValid(classifyBasket.getId())) { - throw new SystemException("创建篮筐实例后仍未获取到篮筐信息,请重试"); - } } - return classifyBasket; } - private void startAndWaitForThread(NewClassifyBasketThread thread) { - int maxRunTime = 5 * 60 * 1000; - try { - thread.start(); - thread.join(maxRunTime); - if (thread.isAlive()) { - thread.interrupt(); - throw new SystemException("创建篮筐实例超时"); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new SystemException("等待创建篮筐实例线程时被中断", e); - } - } /** * 根据回收的篮筐与器械包等生成清洗篮筐实例与清洗物品明细数据 * @param tousseJson 回收的清洗篮筐及器械、标识牌信息,格式:[{amount:1,basketBarcode:'',idCardBarcode:'',tousseDefinitionID:23,tousseName:''},{amount:1,basketBarcode:'',idCardBarcode:'',tousseDefinitionID:23,tousseName:''}]