使用场景:有一组作业等待进程调度执行,每一个作业又包含多个操作,每个操作都是事务性的可以设置为定时或者即时执行。操作事务性的考虑:进程同一时刻只能执行一个操作,下一个操作必须等待上一个操作完成,操作可认为是阻塞性的,定时操作会阻塞掉后方所有操作,操作处于挂起等待状态,正在执行的作业会阻塞掉后面的作业。
相关变量说明:
1) worklist 作业池, 等待执行的批量作业
2) operatelist 操作池, 作业被分解之后的每一个操作
3) cmdlist 进程操作指令队列, 作业被分解成的一组指令
4) status 状态,表示当前作业,操作的状态,有三种状态值 未启动,已启动,正在执行
5) flag 进程调度状态, 目前进程是否处于执行中
6) _pkg 存放进程执行结果
7) _tid 当前执行的work ID, 初始值为0
相关数据结构:
1)作业队列 worklist:
2)操作队列 operatelist
3)进程操作指令队列
算法调度过程:
1)work调度过程(查找已启动的work,分解相关操作,分解每一个操作至指令cmd级)
2)进程调度过程(根据当前进程状态判断是否可以执行指令队列)
3)进程执行完毕回写状态
1)-3)循环
为避免算法复杂,首先不考虑进程在执行cmd过程中的异步性(Asynchronous),这里认为是同步过程(synchronous)
work调度过程分析:
1)扫描整个队列
如果有status=已启动 ,则进入2)
如果有status=正在执行,则跳过整个work调度过程
如果所有status=未启动,则跳过整个work调度过程
2)分解work
分解第一个满足条件的work 插入operatelist队尾, 并修改该work状态为status= 正在执行
3)分解operate
对operate队首取一条operate开始进行分解
3-0 比较operate 中的workid与_tid之间关系,相同则为同一work,不同则上一个work执行完成,需要回写任务状态
3-1 如果operate设置了定时时间,则进入3-2;如果operate为设置定时时间,则进入3-3
3-2 如果operate定时时间> now,则跳出整个调度过程;如果operate定时时间<=now,进入3-3
3-3将队首的operator分解为cmd,插入cmd队列队尾
4)work拆解调度完毕
进程调度过程
1)获取cmd 队首的指令开始执行,并将flag置为忙碌,返回结果保存在_pkg中作为一个operate的操作结果
2)判断cmd是否为空,如果cmd为空_pkg结果为完整的一条operate记录进入3)步骤,否则operate操作尚未完成,跳过3)继续进入作业调度循环
3)清空_pkg,将flag置于空闲
以上算法实现假定了几个条件
1)同一时间只有一个作业处于进程调度中
2)同一时间只有一个cmd会给进程执行
该算法主要利用上述两个假设规避了更复杂情况,如在operate队列中存在多个work的情况,处理速度上会有所影响,但整个算法最终的瓶颈应该还在进程调度cmd中,同一时刻只有一个cmd被进程执行
算法仍然需要优化的地方在
1)work队列的调度上
2)对一个完整的operate执行结束的判断
3)如果CMD为异步命令,比如TCP分包返回的情况下仍需完善