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来进行线程池的方式实现多线程,模拟客户端多用户向同一服务器端发送 ...
随机推荐
- [R]关于R语言的绘图函数
1. 首先就是plot(x,y,...) 参数: x: 所绘图形横坐标构成的对象 y: 所绘图形纵坐标构成的对象 type: 指定所绘图形类型 pch: 指定绘制点时使用的符号 cex: 指定符号的大 ...
- 「雅礼集训 2017 Day2」解题报告
「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...
- 面向对象多继承(c3算法)、网络基础和编写网络相关的程序
一.面向对象多继承(c3算法) a.有多个父类先找左,再找右,如下示例: class A(object): pass class B(object): def f1(self): print('B') ...
- Unable to preventDefault inside passive event listener due to target being treated as passive?
使用滚动时候,新版google浏览器,会弹出如下的警告. 解决方法,可以加上* { touch-action: none; } 这句样式去掉. 其原因:https://developers.googl ...
- django -- 美多订单分表
订单分表: 随着公司业务增长,如果每天1000多万笔订单的话,3个月将有约10亿的订单量,之前数据库采用单表的形式已经不满足于业务需求,数据库改造迫在眉睫. 解决思路: 按月分表,将原订单表拆分为 o ...
- 将celery定时任务设置为根据本地时区触发
默认celery的时区为UTC,如果要在django项目中将celery定时任务配置为根据本地时区触发,则需要修改 在setttings.py 添加以下任意一行: # celery 相关配置 CELE ...
- Python-doc rst文件打开
Python rst文件打开 RST与Python类似Javadoc与Java. 如果下载了别人的Python源码,里面有rst文件夹,我们可以转为html后用浏览器打开 某个开源项目的index.r ...
- copy代码的时候,如何去掉代码前边的编号
从网页上拷贝下来的代码前面总有编号,如何去掉! 1.使用正则表达式:在editorplus(notepad++)里按ctrl+h,弹出框里勾选上“正则表达式(regular expression)”, ...
- 10分钟打造强大的gvim
感谢Ruchee的共享精神,让我等vim新手省去了配置vim的麻烦(教程地址:配置文件使用指南). 只需要简单的6个步骤,就可以配置完成一个强大的gvim神器,下图是我的最终配置效果图. (另外,我的 ...
- [原] ubuntu 13.10 安装 winqq2013
安装及下载地址:http://www.longene.org/forum/viewtopic.php?t=4700 ubuntu 13.10 64位系统安装后无法启动qq,因为缺少程序包.解决方案: ...