多任务并发调度设计

627 阅读3分钟

场景:多个任务场景,既有可并发执行任务也存在依赖关系的任务时。

例如app启动时的检查、目录检查、网络检查、用户信息获取、云端配置信息获取、更新检查、配置检查、设备信息检查。

其中大部分是可以进行并发执行的,但如获取用户信息、配置信息获取,等需要依赖网络检查任务。

如果在启动方法里完成这些,就显得很不优雅,代码也很难维护。这时候就需要一套可以并发自动调度的功能来满足。如果是一个一个写代码臃肿,不好维护,主要是不优雅。

在各种软件中这种场景还是比较多。

调用流程(这里可以是自己认为比较合理的优雅的调用流程,个人建议该流程一定不能复杂,以最低代码量进行设计。想要的结果)

创建原子任务(只管任务功能实现,如检测网络。只实现网络检查,返回执行成功与否,设置上一层依赖关系)->

创建任务调度实例 ->

添加原子任务进列表 ->

execute 执行结束。

设计思路

设计任务列表的排序算法。 为啥能想到拓扑排序算法。 原因是我分析了什么样的结果最合理,有向无环图 比较符合需求。

所以了解到了拓扑排序算法。 然后研究算法原理, 然后根据需求实现算法。topologicalSorting。这边写的比较粗糙,还能进行优化。 得到的拓扑排序结果后,就是任务调度。

按入度顺序依次调用,期间添加任务完成状态,确保后续任务的依赖是完成状态才可进行,代码还可以优化。目前的调度算法只是 按入度进行一排一排执行。

还可以优化成每个原子任务完成后继续调度后续任务。可以根据依赖完成度来决定是否启动下一个任务。这样会更快。 如 2 、4 依赖1 。3依赖 2. 因为2、4是并发任务,目前的设计只能支持2、4完成后在执行3 。其实3的执行和4没有关系。其实可以在2执行完成马上开始执行4,所以这边还可以进行优化来压榨cpu性能。 且还能添加 线程管理。运行的线程。等等 根据业务复杂来设计这个多线程任务调度框架。

具体代码实现

第一步设计原子任务接口

public interface AtomTask {
    //任务
    boolean run();

    // 依赖
    List<Class<?>> dependencies();
}

多线程 任务调度方法

public class MultithreadedTaskScheduling extends Activity {

    ///  任务池
    List<AtomTask> task = new LinkedList<>();


    /// 新增
    public void add(AtomTask atomTask) {
        task.add(atomTask);
    }


    /// 拓扑排序算法
    public List<TaskInfoStruct> topologicalSorting() {
        List<TaskInfoStruct> topologicalTaskInfoList = new LinkedList<>();
        int taskSize = task.size();

        // 计算入度
        for (int i = 0; i < taskSize; i++) {
            TaskInfoStruct topologicalTaskInfo = new TaskInfoStruct();
            AtomTask clsSelf = task.get(i);
            int deep = 0;
            List<Class<?>> clsList = clsSelf.dependencies();
            if (clsList == null) {
                topologicalTaskInfo.setTask(clsSelf);
                topologicalTaskInfo.setPenetration(deep);
                topologicalTaskInfoList.add(topologicalTaskInfo);
                continue;
            }
            deep += 1;

            // 这段代码可以优化
            for (int k = 0; k < clsList.size(); k++) {
                Class<?> item = clsList.get(k);
                for (int l = 0; l < taskSize; l++) {
                    if (task.get(l).getClass().equals(item)) {
                        AtomTask someCls = task.get(l);
                        List<Class<?>> classList = someCls.dependencies();
                        int len = 0;
                        if (classList != null) {
                            len = classList.size();
                        }
                        deep += len;
                    }
                }
            }
            topologicalTaskInfo.setTask(clsSelf);
            topologicalTaskInfo.setPenetration(deep);
            topologicalTaskInfoList.add(topologicalTaskInfo);
        }

        // 按入度进行排序
        Collections.sort(topologicalTaskInfoList, new Comparator<TaskInfoStruct>() {
            @Override
            public int compare(TaskInfoStruct o1, TaskInfoStruct o2) {
                return o1.getPenetration() - o2.getPenetration();
            }
        });
        return topologicalTaskInfoList;
    }

    /// 启动调度
    public void execute() throws InterruptedException {
        // 获取拓扑排序结果
        List<TaskInfoStruct> topologicalTaskInfoList = topologicalSorting();

        // 分组执行
        List<List<TaskInfoStruct>> topologicalTaskInfoMap = new LinkedList<>();
        List<TaskInfoStruct> topologicalTaskInfoList1 = new LinkedList<>();
        for (TaskInfoStruct item : topologicalTaskInfoList) {
            if (topologicalTaskInfoList1.size() == 0) {
                topologicalTaskInfoList1.add(item);
            } else if (topologicalTaskInfoList1.get(0).getPenetration() == item.getPenetration()) {
                topologicalTaskInfoList1.add(item);
            } else {
                topologicalTaskInfoMap.add(topologicalTaskInfoList1);
                topologicalTaskInfoList1 = new LinkedList<>();
                topologicalTaskInfoList1.add(item);
            }
        }
        topologicalTaskInfoMap.add(topologicalTaskInfoList1);
        HashMap<Class<?>, Boolean> okMap = new HashMap<>();
        // 执行 这边还可以进行单任务调度优化。
        for (List<TaskInfoStruct> itemList : topologicalTaskInfoMap) {
            CountDownLatch countDownLatch = new CountDownLatch(itemList.size());

            for (TaskInfoStruct item : itemList) {
                List<Class<?>> list = item.getTask().dependencies();
                if(list!=null){
                    boolean flag = false;
                    for (Class<?> i : list) {
                        flag = Boolean.TRUE.equals(okMap.get(i));
                        if (!flag) {
                            break;
                        }
                    }
                    // 放弃 因为有依赖执行失败了
                    if (!flag) {
                        okMap.put(item.getTask().getClass(), false);
                        countDownLatch.countDown();
                        continue;
                    }
                }

                //这里还可以优化成指定线程
                new Thread(() -> {
                    boolean isOk;
                    // 处理错误 防止别的跑不下去
                    try {
                         isOk = item.getTask().run();
                    }catch (Exception e){
                        e.printStackTrace();
                        isOk = false;
                    }
                    okMap.put(item.getTask().getClass(), isOk);
                    countDownLatch.countDown();
                }).start();
            }
            countDownLatch.await();

        }
    }

}

任务数据结构

class TaskInfoStruct {
    int penetration = 0;
    AtomTask task;

    public AtomTask getTask() {
        return task;
    }

    public void setTask(AtomTask task) {
        this.task = task;
    }

    public int getPenetration() {
        return penetration;
    }

    public void setPenetration(int penetration) {
        this.penetration = penetration;
    }
}