敢说敢作敢为, 无怨无恨无悔。这篇文章主要讲述任务终止的最佳实践相关的知识,希望能为你提供帮助。
设置任务周期性检查的标志,然后任务就能通过自己的shutdown进程并正常终止。不是在任务中随机关闭线程,而是要求任务在到达一个较好时机自行终止。这总能产生比中断更好的结果以及更易理解、更合理的代码。
以这种方式终止任务听起来很简单:设置任务可以看到的boolean flag。编写任务,以便定期检查标志并执行正常终止。这实际上就是你所做的,但有个问题:我们的旧克星,共同的可变状态。若该标志能被另一个任务操纵,则存在碰撞的可能性。
对此,你也知道很多解决这个问题的方法,比如使用volatile。本文将使用更简单的技术并避免所有易变参数。
java 5引入Atomic类,提供了一组可以使用的类型,而不必担心并发问题。
添加AtomicBoolean标志,告诉任务清理自己并退出。
// concurrent/QuittableTask.java
import java.util.concurrent.atomic.AtomicBoolean; import onjava.Nap;
public class QuittableTask implements Runnable
final int id;
public QuittableTask(int id)
this.id = id;
private AtomicBoolean running =
new AtomicBoolean(true);
public void quit()
running.set(false);
@Override
public void run()
while(running.get())// [1]
new Nap(0.1);
System.out.print(id + " "); // [2]
虽然多个任务可以在同一个实例上成功调用quit(),但是AtomicBoolean可以防止多个任务同时实际修改running,从而使quit()方法成为线程安全的。
- [1]:只要运行标志为true,此任务的run()方法将继续。
- [2]: 显示仅在任务退出时发生。
作为测试,我们将启动很多QuittableTasks然后关闭它们。尝试使用较大的COUNT值
// concurrent/QuittingTasks.java
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.*;
import onjava.Nap;
public class QuittingTasks
public static final int COUNT = 150;
public static void main(String[] args)
ExecutorService es =
Executors.newCachedThreadPool();
List< QuittableTask> tasks =
IntStream.range(1, COUNT)
.mapToObj(QuittableTask::new)
.peek(qt -> es.execute(qt))
.collect(Collectors.toList());
new Nap(1);
tasks.forEach(QuittableTask::quit); es.shutdown();
【任务终止的最佳实践】输出结果:
24 27 31 8 11 7 19 12 16 4 23 3 28 32 15 20 63 60 68 6764 39 47 52 51 55 40 43 48 59 44 56 36 35 71 72 83 10396 92 88 99 100 87 91 79 75 84 76 115 108 112 104 107111 95 80 147 120 127 119 123 144 143 116 132 124 128
136 131 135 139 148 140 2 126 6 5 1 18 129 17 14 13 2122 9 10 30 33 58 37 125 26 34 133 145 78 137 141 138 6274 142 86 65 73 146 70 42 149 121 110 134 105 82 117106 113 122 45 114 118 38 50 29 90 101 89 57 53 94 4161 66 130 69 77 81 85 93 25 102 54 109 98 49 46 97
我使用peek()将QuittableTasks传递给ExecutorService,然后将这些任务收集到List.main()中,只要任何任务仍在运行,就会阻止程序退出。即使为每个任务按顺序调用quit()方法,任务也不会按照它们创建的顺序关闭。独立运行的任务不会确定性地响应信号。
推荐阅读
- [ 数据结构 -- 手撕排序算法第七篇 ] 堆及其堆排序
- 图数据库|如何从零到一构建一个企业股权图谱系统
- Oracle密码复杂度PASSWORD_VERIFY_FUNCTION
- flask之活动多开模块包头市政府活动网站开发
- 基于大数据看全球2021年网络攻击态势
- 进程间通信(IPC)—信号
- 类型挑战Unshift,难度??
- # yyds干货盘点 # 盘点一道Python中的yield生成器的题目
- C语言函数(函数的分类,参数,调用,声名及定义)