按照执行时间轮询任务(串行或并行)

自己设计的,不知道有没有坑,慎用


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

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值