自己设计的,不知道有没有坑,慎用
@Component
public class RoundRobinTaskServiceImpl extends AbstractCloudwalkService implements RoundRobinTaskService {
private static ConcurrentHashMap<String, Set<ConcurrentLinkedQueue<CruisePointRoiVo>>> taskRoiMap = new ConcurrentHashMap();
private static ConcurrentHashMap<String, Set<DelayQueue>> taskDelayMap = new ConcurrentHashMap<>();
private static ConcurrentHashMap<String, Set<Thread>> taskThreadMap = new ConcurrentHashMap<>();
@Autowired
@Qualifier("cruiseTaskExecutor")
TaskExecutor taskExecutor;
@Autowired
CwArAlarmRoiManager cwArAlarmRoiManager;
@Autowired
CruiseRoiFilter cruiseRoiFilter;
@Autowired
CwArCruisePointRoiRefManager cwArCruisePointRoiRefManager;
@Autowired
CwArCruisePointManager cwArCruisePointManager;
/**
* 开启串行任务
*
* @param cruiseTask
*/
@Override
public void startSerialTask(CruiseTaskVo cruiseTask) {
//1 获取点位
List<CruisePointVo> pointList = cruiseTask.getCruisePoints();
pointList.stream().sorted(Comparator.comparing(CruisePointVo::getSortNum));
//2 遍历点位列表,获取ROI列表(串行)
ConcurrentLinkedQueue<CruisePointRoiVo> roiList = new ConcurrentLinkedQueue<>();
for (CruisePointVo cruisePoint :
pointList) {
List<CruisePointRoiVo> cruisePointRois = cruisePoint.getCruisePointRois();
if (!CollectionUtils.isEmpty(cruisePointRois)) {
cruisePointRois.stream().sorted(Comparator.comparing(CruisePointRoiVo::getSortNum));
for (CruisePointRoiVo cruisePointRoi :
cruisePointRois) {
roiList.add(cruisePointRoi);
}
}
}
//3 维护预案和roi映射关系
Set<ConcurrentLinkedQueue<CruisePointRoiVo>> roiSet = new HashSet<>();
roiSet.add(roiList);
taskRoiMap.put(cruiseTask.getId(), roiSet);
//4 线程轮询
taskExecutor.execute(new Runnable() {
@Override
public void run() {
try {
processTask(cruiseTask.getId(), roiList);
} catch (DataAccessException e) {
logger.error("数据访问异常:" + e);
} catch (InterruptedException e) {
logger.error("成功关闭线程");
}
}
});
}
/**
* 开启并行任务
*
* @param cruiseTask
*/
@Override
public void startParallelTask(CruiseTaskVo cruiseTask) {
//1 获取点位
List<CruisePointVo> pointList = cruiseTask.getCruisePoints();
pointList.stream().sorted(Comparator.comparing(CruisePointVo::getSortNum));
//2 遍历点位列表,获取ROI列表(并行)
Set<ConcurrentLinkedQueue<CruisePointRoiVo>> roiSet = new HashSet<>();
for (CruisePointVo cruisePoint :
pointList) {
ConcurrentLinkedQueue<CruisePointRoiVo> roiList = new ConcurrentLinkedQueue<>();
if (roiList != null) {
roiList.stream().sorted(Comparator.comparing(CruisePointRoiVo::getSortNum));
for (CruisePointRoiVo cruisePointRoi :
roiList) {
roiList.add(cruisePointRoi);
}
}
roiSet.add(roiList);
}
//3 维护预案对应的roiSet
taskRoiMap.put(cruiseTask.getId(), roiSet);
//4 开启线程轮询roiSet
roiSet.parallelStream().forEach(roiList ->
taskExecutor.execute(new Runnable() {
@Override
public void run() {
try {
processTask(cruiseTask.getId(), roiList);
} catch (Exception e) {
e.printStackTrace();
}
}
}));
}
/**
* 关闭预案
*
* @param taskId
*/
@Override
public void stopTask(String taskId) {
try {
//1 关闭线程
Iterator<Map.Entry<String, Set<Thread>>> threadIterator = taskThreadMap.entrySet().iterator();
while (threadIterator.hasNext()) {
Map.Entry<String, Set<Thread>> next = threadIterator.next();
if (next.getKey().equals(taskId)) {
Set<Thread> threads = next.getValue();
threads.parallelStream().forEach(thread -> {
logger.debug("关闭线程:" + thread);
thread.interrupt();
});
threadIterator.remove();
}
}
//2清空延时队列
Iterator<Map.Entry<String, Set<DelayQueue>>> delayIterator = taskDelayMap.entrySet().iterator();
while (delayIterator.hasNext()) {
Map.Entry<String, Set<DelayQueue>> next = delayIterator.next();
if (next.getKey().equals(taskId)) {
Set<DelayQueue> delayQueues = next.getValue();
delayQueues.parallelStream().forEach(
delayQueue -> {
delayQueue = null;
}
);
delayIterator.remove();
}
}
//3 清空roiList
Iterator<Map.Entry<String, Set<ConcurrentLinkedQueue<CruisePointRoiVo>>>> roiIterator = taskRoiMap.entrySet().iterator();
while (roiIterator.hasNext()) {
Map.Entry<String, Set<ConcurrentLinkedQueue<CruisePointRoiVo>>> next = roiIterator.next();
if (next.getKey().equals(taskId)) {
Set<ConcurrentLinkedQueue<CruisePointRoiVo>> queues = next.getValue();
queues.parallelStream().forEach(queue ->
queue = null);
roiIterator.remove();
}
}
} catch (Exception e) {
logger.error("关闭当前线程出现异常 {}", e);
}
logger.debug("终止当前轮询的预案,taskId:" + taskId);
}
/**
* 获取当前执行的点位中的roi(串行或并行)
*
* @param taskId
*/
@Override
public List<CruisePointVo> getCurrentRoi(String taskId) {
Iterator<Map.Entry<String, Set<ConcurrentLinkedQueue<CruisePointRoiVo>>>> roiIterator = taskRoiMap.entrySet().iterator();
List<CruisePointVo> cruisePointList = new ArrayList<>();
try {
while (roiIterator.hasNext()) {
Map.Entry<String, Set<ConcurrentLinkedQueue<CruisePointRoiVo>>> next = roiIterator.next();
if (next.getKey().equals(taskId)) {
Set<ConcurrentLinkedQueue<CruisePointRoiVo>> queues = next.getValue();
queues.parallelStream().forEach(queue ->
{
CruisePointRoiVo roi = queue.peek();
CwArCurrentPointQueryDTO queryDTO = new CwArCurrentPointQueryDTO();
queryDTO.setRoiId(roi.getRoiId());
queryDTO.setTaskId(taskId);
List<CwArCurrentPointResultDTO> pointResults = cwArCruisePointManager.queryCurrent(queryDTO);
if (!CollectionUtils.isEmpty(pointResults)) {
CruisePointVo cruisePoint = new CruisePointVo();
pointResults.stream().forEach(point -> {
BeanCopyUtils.copyProperties(point, cruisePoint);
cruisePoint.setCurrentRoi(roi);
});
cruisePointList.add(cruisePoint);
}
});
}
}
} catch (Exception e) {
logger.error("查询点位和roi关联失败,原因:" + e);
}
return cruisePointList;
}
/**
* 轮询roi
*
* @param taskId
* @param roiList
*/
private void processTask(String taskId, ConcurrentLinkedQueue<CruisePointRoiVo> roiList) throws DataAccessException, InterruptedException {
// 1 维护预案和线程间关系
if (!CollectionUtils.isEmpty(taskThreadMap.get(taskId))) {
Set<Thread> threads = taskThreadMap.get(taskId);
threads.add(Thread.currentThread());
taskThreadMap.put(taskId, threads);
} else {
Set<Thread> threads = new HashSet<>();
threads.add(Thread.currentThread());
taskThreadMap.put(taskId, threads);
}
// 2 维护预案和延时队列间的关系
DelayQueue delayQueue = new DelayQueue();
if (!CollectionUtils.isEmpty(taskDelayMap.get(taskId))) {
Set<DelayQueue> delayQueues = taskDelayMap.get(taskId);
delayQueues.add(delayQueue);
taskDelayMap.put(taskId, delayQueues);
} else {
Set<DelayQueue> delayQueues = new HashSet<>();
delayQueues.add(delayQueue);
taskDelayMap.put(taskId, delayQueues);
}
// 3 预案轮询
while (roiList != null && !roiList.isEmpty() && !Thread.currentThread().isInterrupted()) {
//当前正在执行的ROI
CruisePointRoiVo cruisePointRoi = roiList.peek();
//3 获取围界,并判断其是否在有效时间
boolean valid = false;
CwArAlarmRoiGetsDTO getsDTO = new CwArAlarmRoiGetsDTO();
getsDTO.setId(cruisePointRoi.getRoiId());
List<CwArAlarmRoiResultDTO> getsResult = null;
try {
getsResult = cwArAlarmRoiManager.gets(getsDTO);
} catch (DataAccessException | InterruptedException exception) {
throw exception;
}
try {
if (!CollectionUtils.isEmpty(getsResult) && getsResult.get(0) != null
&& getsResult.get(0).getRoiTask() != null) {
RoiTask roiTask = getsResult.get(0).getRoiTask();
valid = cruiseRoiFilter.isMatchTask(roiTask);
}
Thread.sleep(1);
if (valid) {
//4 将当前运行的roi放入延时队列,执行时间到了放入队尾
DelayTask delayTask = new DelayTask(cruisePointRoi, cruisePointRoi.getExecutionTime());
logger.debug("预案 {} 当前轮询到的roi {}", taskId, JsonUtils.toJson(cruisePointRoi));
delayQueue.put(delayTask);
delayQueue.take();
if (!roiList.isEmpty()) {
CruisePointRoiVo pollRoi = roiList.poll();
roiList.offer(pollRoi);
}
} else {
//5 非有效的roi,直接放入队尾
if (!roiList.isEmpty()) {
CruisePointRoiVo pollRoi = roiList.poll();
logger.debug("预案 {} 无效的roi {},不参与轮询", taskId, JsonUtils.toJson(pollRoi));
roiList.offer(pollRoi);
}
}
} catch (InterruptedException exception) {
throw exception;
}
}
}
}