代码更新:

1. 修复出库
2. 非计划领料修复
3. 增加多线程
This commit is contained in:
梁州 2024-09-28 17:03:30 +08:00
parent 3b25a93b5e
commit f968c83ca1
4 changed files with 66 additions and 33 deletions

View File

@ -2,8 +2,8 @@ package com.wms.config;
import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor; import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
@ -12,9 +12,9 @@ import java.util.concurrent.ThreadPoolExecutor;
* 线程池配置 * 线程池配置
*/ */
@SpringBootConfiguration @SpringBootConfiguration
@EnableAsync
public class ThreadPoolConfig { public class ThreadPoolConfig {
@Bean @Bean("myThreadPool")
// @Bean("pool1")
public TaskExecutor taskExecutor() { public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数 // 设置核心线程数
@ -24,7 +24,7 @@ public class ThreadPoolConfig {
// 设置队列容量 // 设置队列容量
executor.setQueueCapacity(100); executor.setQueueCapacity(100);
// 设置线程活跃时间 // 设置线程活跃时间
executor.setKeepAliveSeconds(60); executor.setKeepAliveSeconds(300);
// 设置线程默认名称前缀 // 设置线程默认名称前缀
executor.setThreadNamePrefix("wmsThreadPool-"); executor.setThreadNamePrefix("wmsThreadPool-");
// 设置拒绝策略 // 设置拒绝策略

View File

@ -11,6 +11,8 @@ import lombok.RequiredArgsConstructor;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
@ -28,6 +30,7 @@ import java.util.*;
*/ */
@Component @Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) @RequiredArgsConstructor(onConstructor = @__(@Autowired))
@EnableAsync
public class JobComponent { public class JobComponent {
private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final Logger logger = LoggerFactory.getLogger(this.getClass());
/** /**
@ -48,6 +51,7 @@ public class JobComponent {
* 每2秒执行一次 * 每2秒执行一次
*/ */
@Scheduled(fixedDelay = 2000) @Scheduled(fixedDelay = 2000)
@Async("myThreadPool")
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void sendCommonTasks() { public void sendCommonTasks() {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
@ -68,6 +72,7 @@ public class JobComponent {
* 每2秒执行一次 * 每2秒执行一次
*/ */
@Scheduled(fixedDelay = 2000) @Scheduled(fixedDelay = 2000)
@Async("myThreadPool")
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void sendPickOutTasks() { public void sendPickOutTasks() {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_PICK_OUT_TASK.getConfigKey()); String sendTask = configMap.get(ConfigMapKeyEnum.SEND_PICK_OUT_TASK.getConfigKey());
@ -88,6 +93,7 @@ public class JobComponent {
* 每2秒执行一次 * 每2秒执行一次
*/ */
@Scheduled(fixedDelay = 2000) @Scheduled(fixedDelay = 2000)
@Async("myThreadPool")
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void sendPickTasks() { public void sendPickTasks() {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
@ -107,7 +113,8 @@ public class JobComponent {
* 重复入库任务 * 重复入库任务
* 每2秒执行一次 * 每2秒执行一次
*/ */
@Scheduled(fixedDelay = 2000) // @Scheduled(fixedDelay = 2000)
@Async("myThreadPool")
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void solveDuplicateTask() { public void solveDuplicateTask() {
String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
@ -127,6 +134,7 @@ public class JobComponent {
* 创建工作 * 创建工作
*/ */
@Scheduled(fixedDelay = 2000) @Scheduled(fixedDelay = 2000)
@Async("myThreadPool")
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void createWork() { public void createWork() {
String createWork = configMap.get(ConfigMapKeyEnum.CREATE_WORK.getConfigKey()); String createWork = configMap.get(ConfigMapKeyEnum.CREATE_WORK.getConfigKey());
@ -153,6 +161,7 @@ public class JobComponent {
* 执行工作 * 执行工作
*/ */
@Scheduled(fixedDelay = 2000) @Scheduled(fixedDelay = 2000)
@Async("myThreadPool")
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void doWork() { public void doWork() {
String startWork = configMap.get(ConfigMapKeyEnum.START_WORK.getConfigKey()); String startWork = configMap.get(ConfigMapKeyEnum.START_WORK.getConfigKey());
@ -180,6 +189,7 @@ public class JobComponent {
* 每天晚上10点执行一次 * 每天晚上10点执行一次
*/ */
@Scheduled(cron = "0 0 22 * * ?") @Scheduled(cron = "0 0 22 * * ?")
@Async("myThreadPool")
public void deleteOutOfDateData() { public void deleteOutOfDateData() {
// 删除日志数据 // 删除日志数据
wmsJobService.deleteLogsRegularly(); wmsJobService.deleteLogsRegularly();

View File

@ -1200,7 +1200,6 @@ public class TaskController {
GoodsToStation goodsToStation = goodsToStationService.getOne(new LambdaQueryWrapper<GoodsToStation>() GoodsToStation goodsToStation = goodsToStationService.getOne(new LambdaQueryWrapper<GoodsToStation>()
.eq(GoodsToStation::getWorkStation, workFlow.getWorkStation()) .eq(GoodsToStation::getWorkStation, workFlow.getWorkStation())
.eq(GoodsToStation::getGoodsId, workFlow.getGoodsId()) .eq(GoodsToStation::getGoodsId, workFlow.getGoodsId())
// .lt(GoodsToStation::getDistributeStatus, 2)
.last("limit 1")); .last("limit 1"));
if (goodsToStation != null) { if (goodsToStation != null) {
// 更新站台要料数量 // 更新站台要料数量
@ -1209,24 +1208,27 @@ public class TaskController {
goodsToStation.setDistributeStatus(1); goodsToStation.setDistributeStatus(1);
goodsToStationService.updateById(goodsToStation); goodsToStationService.updateById(goodsToStation);
} }
} workFlow.setLightStatus(0);// 未亮灯
if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) < 0) { workFlow.setWorkStatus(1);// 正在做
// 判断后续有无物料进此站台
List<PickTask> pickedTasks = pickTaskService.list(new LambdaQueryWrapper<PickTask>()
.eq(PickTask::getStandId, workFlow.getWorkStation())
.ne(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode()));
if (!pickedTasks.isEmpty()) {
List<String> vehicleIds = pickedTasks.stream().map(PickTask::getVehicleId).distinct().toList();
if (outsideVehiclesService.exists(new LambdaQueryWrapper<OutsideVehicles>()
.eq(OutsideVehicles::getGoodsId, workFlow.getGoodsId())
.in(OutsideVehicles::getVehicleId, vehicleIds))) {
workFlow.setLightStatus(0);// 未亮灯
workFlow.setWorkStatus(1);// 正在做
}
}
} else { } else {
workFlow.setLightStatus(2);// 已拍灯 if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) < 0) {
workFlow.setWorkStatus(2);// 已完成 // 判断后续有无物料进此站台
List<PickTask> pickedTasks = pickTaskService.list(new LambdaQueryWrapper<PickTask>()
.eq(PickTask::getStandId, workFlow.getWorkStation())
.ne(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode()));
if (!pickedTasks.isEmpty()) {
List<String> vehicleIds = pickedTasks.stream().map(PickTask::getVehicleId).distinct().toList();
if (outsideVehiclesService.exists(new LambdaQueryWrapper<OutsideVehicles>()
.eq(OutsideVehicles::getGoodsId, workFlow.getGoodsId())
.in(OutsideVehicles::getVehicleId, vehicleIds))) {
workFlow.setLightStatus(0);// 未亮灯
workFlow.setWorkStatus(1);// 正在做
}
}
} else {
workFlow.setLightStatus(2);// 已拍灯
workFlow.setWorkStatus(2);// 已完成
}
} }
// 更新workFlow // 更新workFlow
workFlow.setFinishTime(LocalDateTime.now()); workFlow.setFinishTime(LocalDateTime.now());
@ -1242,7 +1244,7 @@ public class TaskController {
goodsDetail.setRemainNum(goodsDetail.getRemainNum().subtract(BigDecimal.valueOf(eTaskFeedbackRequest.getConfirmNum()))); goodsDetail.setRemainNum(goodsDetail.getRemainNum().subtract(BigDecimal.valueOf(eTaskFeedbackRequest.getConfirmNum())));
existStock.setGoodsRelated(goodsDetail); existStock.setGoodsRelated(goodsDetail);
stockService.updateById(existStock); stockService.updateById(existStock);
stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.KITTING_UPDATE.getReason(), "电子标签灯光反馈"); stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.KITTING_UPDATE.getReason(), workFlow.getWorkStation() + "-电子标签灯光反馈");
} }
// 更新电子标签库位信息 // 更新电子标签库位信息
etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>() etagLocationService.update(new LambdaUpdateWrapper<ETagLocation>()
@ -2413,7 +2415,8 @@ public class TaskController {
tempOutTask.setCreateTime(LocalDateTime.now()); tempOutTask.setCreateTime(LocalDateTime.now());
tempOutTask.setIsPicking(1); tempOutTask.setIsPicking(1);
outTasks.add(tempOutTask); outTasks.add(tempOutTask);
} else if (Objects.equals(tempStock.getStockStatus(), StockStatus.OUT.getCode())) { } else if (Objects.equals(tempStock.getStockStatus(), StockStatus.OUT.getCode())
|| Objects.equals(tempStock.getStockStatus(), StockStatus.PICKING.getCode())) {
// 查询这个箱子的拣选任务 // 查询这个箱子的拣选任务
List<PickTask> thisVehiclePickTasks = pickTaskService.list(new LambdaQueryWrapper<PickTask>() List<PickTask> thisVehiclePickTasks = pickTaskService.list(new LambdaQueryWrapper<PickTask>()
.eq(PickTask::getVehicleId, tempStock.getVehicleId())); .eq(PickTask::getVehicleId, tempStock.getVehicleId()));
@ -2437,7 +2440,7 @@ public class TaskController {
// 将这个箱子对应的出库任务优先级设置位2 // 将这个箱子对应的出库任务优先级设置位2
taskService.update(new LambdaUpdateWrapper<Task>() taskService.update(new LambdaUpdateWrapper<Task>()
.set(Task::getTaskPriority, 2) .set(Task::getTaskPriority, 2)
.eq(Task::getTaskId, tempStock.getVehicleId()) .eq(Task::getVehicleId, tempStock.getVehicleId())
.eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()));
thisVehiclePickTasks.forEach(pickTask -> { thisVehiclePickTasks.forEach(pickTask -> {
if (!pickStandIds.contains(pickTask.getStandId())) { if (!pickStandIds.contains(pickTask.getStandId())) {

View File

@ -163,7 +163,8 @@ public class WmsJobServiceImplements implements IWmsJobService {
// 检索任务表---新建未下发的任务 // 检索任务表---新建未下发的任务
LambdaQueryWrapper<Task> waitForDistributeTaskQuery = new LambdaQueryWrapper<Task>() LambdaQueryWrapper<Task> waitForDistributeTaskQuery = new LambdaQueryWrapper<Task>()
.eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()) .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())
.eq(Task::getTaskType, TaskType.OUT.getCode()); .eq(Task::getTaskType, TaskType.OUT.getCode())
.eq(Task::getTaskPriority, 1);
List<Task> allTasks = taskService.list(waitForDistributeTaskQuery); List<Task> allTasks = taskService.list(waitForDistributeTaskQuery);
if (!allTasks.isEmpty()) { if (!allTasks.isEmpty()) {
String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey()); String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey());
@ -195,12 +196,14 @@ public class WmsJobServiceImplements implements IWmsJobService {
List<PickTask> standPickTasks = pickTaskService.list(); List<PickTask> standPickTasks = pickTaskService.list();
// 生成一个Map计算每个站台已经出库的拣选任务 // 生成一个Map计算每个站台已经出库的拣选任务
Map<String, Integer> outPickTaskMap = new HashMap<>(); Map<String, Integer> outPickTaskMap = new HashMap<>();
Map<String, Integer> updatedOutPickTaskMap = new HashMap<>();
// 轮询工作站台判断是否需要下发任务 // 轮询工作站台判断是否需要下发任务
List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>() List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
.eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
.eq(Stand::getStandType, 2)); .eq(Stand::getStandType, 2));
for (Stand workStation : stands) { for (Stand workStation : stands) {
outPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount()); outPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount());
updatedOutPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount());
} }
// 轮询堆垛机状态 // 轮询堆垛机状态
List<Stand> stackerList = standService.list(new LambdaQueryWrapper<Stand>() List<Stand> stackerList = standService.list(new LambdaQueryWrapper<Stand>()
@ -224,7 +227,7 @@ public class WmsJobServiceImplements implements IWmsJobService {
break; break;
} }
if (runningTaskNumToEquipmentMap.containsKey(key)) { if (runningTaskNumToEquipmentMap.containsKey(key)) {
if (runningTaskNumToEquipmentMap.get(key) >= 2) { if (runningTaskNumToEquipmentMap.get(key) >= 4) {
runningTaskNumToEquipmentMap.remove(key); runningTaskNumToEquipmentMap.remove(key);
} else { } else {
runningTaskNumToEquipmentMap.replace(key, runningTaskNumToEquipmentMap.get(key) + 1); runningTaskNumToEquipmentMap.replace(key, runningTaskNumToEquipmentMap.get(key) + 1);
@ -329,7 +332,10 @@ public class WmsJobServiceImplements implements IWmsJobService {
} }
if (flag) { if (flag) {
if (!maxStandIds.isEmpty()) { if (!maxStandIds.isEmpty()) {
maxStandIds.forEach(tempStandId -> outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1)); maxStandIds.forEach(tempStandId -> {
outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1);
updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1);
});
} }
runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1); runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1);
// 已经发送过的vehicleId // 已经发送过的vehicleId
@ -342,6 +348,10 @@ public class WmsJobServiceImplements implements IWmsJobService {
skipVehicleIds.add(maxVehicleId); skipVehicleIds.add(maxVehicleId);
} }
} }
} else {
if (!skipVehicleIds.contains(maxVehicleId)) {
skipVehicleIds.add(maxVehicleId);
}
} }
} }
// 最少使用的箱子 // 最少使用的箱子
@ -392,7 +402,10 @@ public class WmsJobServiceImplements implements IWmsJobService {
} }
if (flag) { if (flag) {
if (!minStandIds.isEmpty()) { if (!minStandIds.isEmpty()) {
minStandIds.forEach(tempStandId -> outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1)); minStandIds.forEach(tempStandId -> {
outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1);
updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1);
});
} }
runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1); runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1);
// 已经发送过的vehicleId // 已经发送过的vehicleId
@ -405,11 +418,18 @@ public class WmsJobServiceImplements implements IWmsJobService {
skipVehicleIds.add(minVehicleId); skipVehicleIds.add(minVehicleId);
} }
} }
} else {
if (!skipVehicleIds.contains(minVehicleId)) {
skipVehicleIds.add(minVehicleId);
}
} }
} }
List<Integer> removeKeys = new ArrayList<>(runningTaskNumToEquipmentMap.keySet().stream().toList()); List<Integer> removeKeys = new ArrayList<>(runningTaskNumToEquipmentMap.keySet().stream().toList());
for (int equipmentId : removeKeys) { for (int equipmentId : removeKeys) {
if (runningTaskNumToEquipmentMap.get(equipmentId) >= 2) { // 剩余任务有没有这台堆垛机的
List<Task> remainTasks = allTasks.stream().filter(task -> !skipVehicleIds.contains(task.getVehicleId()) && !pickVehicleIds.contains(task.getVehicleId())
&& task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList();
if (remainTasks.isEmpty() || runningTaskNumToEquipmentMap.get(equipmentId) >= 4) {
runningTaskNumToEquipmentMap.remove(equipmentId); runningTaskNumToEquipmentMap.remove(equipmentId);
} }
} }
@ -444,9 +464,9 @@ public class WmsJobServiceImplements implements IWmsJobService {
.set(OutsideVehicles::getOutStatus, 1) .set(OutsideVehicles::getOutStatus, 1)
.in(OutsideVehicles::getVehicleId, pickVehicleIds)); .in(OutsideVehicles::getVehicleId, pickVehicleIds));
// 更新站台拣选箱数 // 更新站台拣选箱数
for (String tempStandId : outPickTaskMap.keySet()) { for (String tempStandId : updatedOutPickTaskMap.keySet()) {
standService.update(new LambdaUpdateWrapper<Stand>() standService.update(new LambdaUpdateWrapper<Stand>()
.set(Stand::getPickVehicleCount, outPickTaskMap.get(tempStandId)) .set(Stand::getPickVehicleCount, updatedOutPickTaskMap.get(tempStandId))
.eq(Stand::getStandId, tempStandId)); .eq(Stand::getStandId, tempStandId));
} }
} }