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]
Java“毒丸”使用示例,实现取消任务的更多相关文章
- [译]Java Thread Sleep示例
Java Thread Sleep示例 java.lang.Thread sleep(long millis)方法被用来暂停当前线程的执行,暂停时间由方法参数指定,单位为毫秒.注意参数不能为负数,否则 ...
- [译]Java Thread join示例与详解
Java Thread join示例与详解 Java Thread join方法用来暂停当前线程直到join操作上的线程结束.java中有三个重载的join方法: public final void ...
- 多线程Java Socket编程示例
package org.merit.test.socket; import java.io.BufferedReader; import java.io.IOException; import jav ...
- Java开发Hbase示例
Java开发Hbase示例 使用Hbase操作数据 package com.sunteng.clickidc.test; import java.io.IOException; import java ...
- Java代理模式示例程序
Java代理模式示例程序 当然不是我想出来的,是我看的一个网上教程里的. 模拟的是一个对电脑公司的代理 真实类的接口: public interface SaleComputer { public S ...
- Java广度优先爬虫示例(抓取复旦新闻信息)
一.使用的技术 这个爬虫是近半个月前学习爬虫技术的一个小例子,比较简单,怕时间久了会忘,这里简单总结一下.主要用到的外部Jar包有HttpClient4.3.4,HtmlParser2.1,使用的开发 ...
- java 动态代理示例,带主要注释
Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...
- 从一个简单的Java单例示例谈谈并发
一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...
- 多线程Java Socket编程示例(转)
这篇做为学习孙卫琴<<Java网络编程精解>>的学习笔记吧.其中采用Java 5的ExecutorService来进行线程池的方式实现多线程,模拟客户端多用户向同一服务器端发送 ...
随机推荐
- DevExpress中获取GridControl排序之后的List
public System.Collections.IList GetGridViewFilteredAndSortedData(DevExpress.XtraGrid.Views.Grid.Grid ...
- MVC 5 Strongly Typed Views(强类型视图)
学习MVC这样久以来,发觉网站上很多MVC的视频或是文章,均是使用Strongly Type views来实现控制器与视图的交互.Insus.NET以前发布的博文中,也大量使用这种方式: <Da ...
- [leetcode.com]算法题目 - Gray Code
The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...
- 【Vue】浅谈Vue不同场景下组件间的数据交流
浅谈Vue不同场景下组件间的数据“交流” Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完 ...
- Django 实现第三方账号登录网站
这里我们使用 django-allauth 模块来实现第三方账号验证登录,官方文档如下:https://django-allauth.readthedocs.io/en/latest/ . 安装 dj ...
- underscore.js源码研究(1)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- Shell - 简明Shell入门02 - 变量(Variable)
示例脚本及注释 #!/bin/bash v1=test-variable_123 # 全局变量 v2=12345 v3='This is a test!' # 赋值语句使用单引号或双引号可以包含空格 ...
- 课程一(Neural Networks and Deep Learning),第四周(Deep Neural Networks)—— 0.学习目标
Understand the key computations underlying deep learning, use them to build and train deep neural ne ...
- matlab中元胞数组的创建与内容读取
一.创建元胞数组 1.用cell命令创建规格为2*2的空元胞 >> a=cell(2,2) a = [] [] [] [] 2.用大括号"{}"创建元胞数组并赋值 &g ...
- 三:理解Page类的运行机制(例:在render方法中生成静态文件)
我这里只写几个常用的事件1.OnPreInit:此事件后将加载个性化信息和主题2.OnInit:初始化页面中服务器控件的默认值但控件的状态没有加载,没有创建控件树3.OnPreLoad:控件完成状态和 ...