带有序子任务的任务需等待未知阻塞清除后执行的技术咨询
解决方案:带有序子任务与阻塞启动的任务设计
看起来你需要的是一套既能固定子任务执行顺序,又能在未知阻塞项清除后才启动的任务架构,结合你举的冰淇淋消费例子,这里给你一套实用的设计思路和代码示例:
核心设计思路
我推荐用模板方法模式来固化子任务的执行流程,再配合一个灵活的阻塞项检查机制,这样既能保证顺序不混乱,又能适配不同任务的未知阻塞条件:
- 模板方法负责把Buy、Open、Eat这些子任务的顺序焊死,所有同类任务都遵循这个流程;
- 阻塞检查逻辑交给具体任务自己实现,毕竟每个任务的阻塞项(比如自己的工作、孩子的作业)都是不一样的。
伪代码实现示例
先搞一个抽象基类,把通用的流程和启动逻辑封装好:
abstract class IcecreamConsumptionTask { // 固定子任务顺序的模板方法,子类不能修改这个流程 protected final void runTaskSequence() { buyIcecream(); openIcecream(); eatIcecream(); } // 子类必须实现的具体子任务 protected abstract void buyIcecream(); protected abstract void openIcecream(); protected abstract void eatIcecream(); // 子类自定义阻塞项检查逻辑——因为阻塞项是未知的,交给具体任务来判断 protected abstract boolean isAllBlockersCleared(); // 公共启动入口,包含阻塞等待逻辑 public void start() { // 循环等待,直到所有阻塞项都清除 while (!isAllBlockersCleared()) { // 加个延迟避免空轮询,实际场景也可以用监听/回调代替轮询 try { Thread.sleep(1000); System.out.println("还在等阻塞项清除..."); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } // 阻塞项搞定,开始执行子任务序列 runTaskSequence(); } }
然后是你的ConsumeIcecream任务,实现自己的子任务和阻塞检查:
class ConsumeIcecream extends IcecreamConsumptionTask { @Override protected void buyIcecream() { System.out.println("买一支巧克力味冰淇淋"); } @Override protected void openIcecream() { System.out.println("撕开冰淇淋的塑料包装"); } @Override protected void eatIcecream() { System.out.println("美滋滋地吃掉冰淇淋"); } @Override protected boolean isAllBlockersCleared() { // 这里模拟你的阻塞项,比如是否完成了手头的工作 return isWorkCompleted(); } // 自定义的阻塞项检查逻辑 private boolean isWorkCompleted() { // 实际场景替换成真实的判断条件 return true; } // 你提到的SpoilYourself启动方法,其实就是封装start() public void SpoilYourself() { this.start(); } }
再搞LetKidConsumeIcecream任务,适配孩子的场景:
class LetKidConsumeIcecream extends IcecreamConsumptionTask { @Override protected void buyIcecream() { System.out.println("给孩子买一支草莓味冰淇淋"); } @Override protected void openIcecream() { System.out.println("帮孩子拆开冰淇淋包装"); } @Override protected void eatIcecream() { System.out.println("看着孩子开心地啃冰淇淋"); } @Override protected boolean isAllBlockersCleared() { // 孩子的阻塞项可能是作业有没有写完 return isKidHomeworkDone(); } private boolean isKidHomeworkDone() { // 实际场景替换成真实判断 return true; } }
为什么这么设计?
- 顺序绝对可控:模板方法用
final修饰,子类没法修改子任务的执行顺序,完全符合你“既定顺序执行”的要求; - 阻塞项灵活适配:每个任务可以根据自己的情况定义阻塞检查逻辑,不管是啥未知的阻塞项都能套进去;
- 代码复用性强:基类已经把启动等待、流程控制这些通用逻辑搞定了,子类只需要实现自己的业务细节就行,不用重复造轮子。
内容的提问来源于stack exchange,提问作者Tryggen
相关产品推荐
相关产品推荐

