系列文章:
接上一篇:我们切分了dag并开始提交stage任务到线程池执行。
那么这样就带来了一些问题
1.如何判断某个步骤是否执行结束
2.如何判断整个转换是否结束
3.当某个步骤出错时,我们如何停止整个转换。
...
事件通知
首先,我们通过定义事件和事件handler的方式,通过接收事件的方式完成对事件的处理。
先定义一个事件:
再定义一个事件的处理器:
接着定义事件的类型
有了事件,我们就可以根据事件和事件的处理来处理我们上述的几个问题。
接下来,我们就分别以几种执行策略来分别实现。
策略1:每个步骤一个线程
1.1首先,我们对每个管道设置两个标识符,分别是,写入完成标识,读取完成标识。
1.2输入步骤,在处理数据的时候判断是否还有下一行,没有下一行时候,手动标记步骤完成。
标记步骤完成会设置当前步骤的所有输出管道的写入完成标识为true
1.3非输入步骤,不断从输入管道拉取数据,当管道获取数据为null时,且该管道被标记为写入完
成,则标记该管道读取完成。
1.4非输入步骤,继续从该管道拉取数据(过滤读取完成的管道),当所有输入管道被标记为读取
完成的时候,代表该步骤执行结束,然后标记所有输出管道的写入完成标识为true。
1.5 然后循环1.3和1.4
以上的逻辑能够完成对步骤是否结束的判断,那么我们如何判断整个转换是否结束呢?
这个时候就要使用到我们的事件了。
在执行类里面,定义一个变量:nrOfFinishedSteps。这个变量代表执行完成的任务数量。
然后在执行类里面定义一个步骤的事件处理器。
这个事件处理器接收到任务完成事件后,会更新nrOfFinishedSteps。
当nrOfFinishedSteps和任务数量相等时候,代表整个转换执行完成。
接下来,为每个执行任务添加这个事件处理器。
这样,我们只需要在任务完成时候,触发这个事件即可。
step.fireEvent(EventTypes.StepFinished);
其他问题的解决办法也类似上面。
策略2:每个stage一个线程
此种执行策略和策略1的判断逻辑是类似的。
不同点:串联步骤的第一个步骤结束,也即代表整个串联步骤的结束
因此我们添加事件处理器的时候,不必对串联的每一个步骤添加,只需要对第一个步骤添加即可。