zoukankan      html  css  js  c++  java
  • 六、Java“毒丸”使用示例,实现取消任务

    一、简介

    在Java并发编程中,“毒丸”指的是将一个对象放在队列当中,当得到这个对象的时候立即停止执行

    下面是一个使用“毒丸”来取消任务的一个示例

    如图所示,我们假设一个任务从开始到结束需要经历4个步骤,正常情况下4个步骤将会顺序执行。

    而在任务的执行过程中,我们由于一些原因需要取消这个任务,那这个时候我们设置一个“毒丸”,每个步骤在执行开始的时候会进行校验,如果遇到“毒丸”那么将终止执行。

    考虑到添加“毒丸”的时候,上一个任务可能还在执行中,所以添加毒丸以后,需要对上一个步骤进行清理,例如:上一个步骤是在查询数据库,那么可能你需要把数据库的查询中断掉

    二、示例代码

    PoisonDemo

    public class PoisonDemo {
        public static void main(String[] args) {
            // 实例化一个任务
            final Task task = new Task();
            // 另起一个线程,在2秒以后取消任务
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    task.cancel();
                }
            }).start();
            // 主线程执行任务
            task.execute();
        }
    }

    Task

    public class Task {
        private String[]          stepNames    = { "step1", "step2", "step3", "step4" };
        private int               currentIndex = 0;
        private TaskCancelManager manager      = new TaskCancelManager();
    
        public void execute() {
            System.out.println("任务开始执行 steps=" + Arrays.asList(stepNames));
            Step currStep = null;
            while (true) {
                if (currentIndex + 1 > stepNames.length) {
                    break;
                }
                // 执行任务
                String  stepName = stepNames[currentIndex];
                boolean success  = manager.addStep(stepName);
                if (!success) {
                    System.out.println(stepName + " 不继续执行");
                    // 清理上一个步骤的数据
                    if (currStep != null) {
                        currStep.purge();
                    }
                    break;
                }
                // 获取当前步骤,并执行
                currStep = new Step(stepName);
                currStep.execute();
                currentIndex++;
            }
            System.out.println("任务执行结束 steps=" + manager.getStepNames());
        }
    
        public void cancel() {
            manager.addPoison();
        }
    }

    Step

    public class Step {
        private String stepName;
    
        public Step(String stepName) {
            this.stepName = stepName;
        }
    
        public void execute() {
            System.out.println(stepName + " 开始执行");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(stepName + " 结束执行");
        }
    
        public void purge() {
            System.out.println("任务中断,清理" + stepName + "步骤");
        }
    }

    TaskCancelManager:这里采用同步锁来控制添加“毒丸”和“步骤”是互斥的

    public class TaskCancelManager {
        private static final String POISON = "poison";
    
        private List<String> stepNames = new ArrayList<String>();
    
        public synchronized boolean addStep(String stepName) {
            // 如果上一个是毒丸
            if (stepNames.size() > 0 && stepNames.get(stepNames.size() - 1).equals(POISON)) {
                return false;
            }
            stepNames.add(stepName);
            return true;
        }
    
        public synchronized void addPoison() {
            stepNames.add(POISON);
        }
    
        public List<String> getStepNames() {
            return stepNames;
        }
    }

    我们运行程序,最后输出内容为:

    任务开始执行 steps=[step1, step2, step3, step4]
    step1 开始执行
    step1 结束执行
    step2 开始执行
    step2 结束执行
    step3 不继续执行
    任务中断,清理step2步骤
    任务执行结束 steps=[step1, step2, poison]
  • 相关阅读:
    layui 自定义统一监听事件(大范围)
    layui 自定义个别事件
    Django layui {{ }}冲突解决方法
    sudo apt install ...
    Field XXX in XXXX required a bean of type XXXX that could not be found
    Springboot2+bootstrap-table1.12.1+MybatisPlus3.0 后台物理分页实现
    springboot2在后台打印系统执行的SQL
    @Service注解让spring找到你的Service bean
    接受参数的包装类的数据类型写错报错
    Java 日期转字符串
  • 原文地址:https://www.cnblogs.com/lay2017/p/10524816.html
Copyright © 2011-2022 走看看