并发编程实战:取消和关闭
任务和线程的启动很容易。在大多数时候,我们都会让它们运行直到结束,或者让它们自行停止。然而,有时候我们希望提前结束任务或线程,或许是因为用户取消了操作,或者应用程序需要被快速关闭。
要使任务和线程能安全、快速、可靠地停止下来,并不是一件容易的事。Java没有提供任何机制来安全地终止线程(虽然Thread.stop和suspend等方法提供了这样的机制,但是由于存在着一些严重的缺陷,因此避免使用),但它提供了中断(Interruption),这是一种协作机制,能够使一个线程终止另一个线程的当前工作。
一、任务取消
如果外部代码能在某个操作正常完成之前将其置入“完成”状态,那么这个操作就可以称为可取消的(Cancellable)。取消某个操作的原因很多:
1.用户请求取消
2.有时间限制的操作
3.应用程序事件
4.错误:
5.关闭:
在java中没有一种安全的抢占式方法来停止线程,因此也就没有安全的抢占式方法来停止任务。只有一些协作式的机制,使请求取消的任务和代码都遵循一种协商好的协议。其中一种协作机制能设置某个“已请求取消”标志,而任务将定期地查看该标志。如果设置来这个标志,那么任务将提前结束。复制代码
示例
其中PrimeGenerator持续地枚举素数,直到它被取消。cancel方法将设置cancelled标志,并且主循环在搜索下一个素数之前会首先检查这个标志(为了使这个过程可靠的工作,标志cancelled必须为volatile类型)
pulbic class PrimeGenerator implements Runnable{private final List<BigInteger> primes = new ArrayList<BigInteger>;//使用volatile类型的域来保存取消状态private volatile boolean cancelled;public void run(){BigInteger p = BigInteger.ONE; while(!cancelled){p = p.nextProbablePrime(); synchronized (this) {primes.add(p);}}}public void cancel(){cancelled = true;}public synchronized List<BigInteger> get(){teturn new ArrayList<BigInteger>(primes);}}复制代码
下边是PrimeGenerator的使用示例,即让素数生成器运行1秒钟后取消。素数生成器通常不会刚好在运行一秒钟后停止,因为在请求取消的时刻和run方法中循环执行下一次检查之间可能存在延迟。cancel方法由finally块调用,从而确保即使在调用sleep时被中断也能取消素数生成器的执行。如果cancel没有被调用,那么搜索素数的线程将永远运行下去,不断消耗CPU的时钟周期,并使得JVM不能正常退出。
List<BigInteger> aSecondOfPeimes() throws InterruptionException{PrimeGenerator primeGenerator = new PrimeGenerator();new Thread(primeGenerator).start();try{SECONDS.sleep(1); }finally {primeGenerator.cancel();}return primeGenerator.get();}
primeGenerator使用了一种简单的取消策略:客户代码通过调用cancel来请求取消,primeGenerator在每次搜索素数之前首先检查是否存在取消请求,如果存在则退出。
复制代码
总结:
一个可取消的任务必须拥有取消策略(Cancellation Policy),在这个策略中将详细地定义取消操作的“How”、“When”、“What”,即其他代码如何(How)请求取消任务,任务在何时(When)检查是否已经请求了取消,以及在响应取消请求时应该执行哪些(What)操作。
举例
考虑现实世界中停止支付支票的示例。银行通常会规定如何提交一个停止支付的请求,在处理这些请求时需要作出哪些响应性保证,以及当支付中断后需要遵守哪些流程(例如通知该事务中涉及的其他银行,以及对付款人的账户进行费用评估)。这些流程和保证放在一起就构成了支票支付的取消策略。
二、中断
primeGenerator中的取消机制最终会使得搜索素数的任务退出,但在退出过程中需要花费一定的时间,然而,如果使用这种方法的任务调用一个阻塞方法,例如BlockingQueue.put,那么可能会产生一个更严重的问题——任务可能永远不会检查取消标志,因此永远不会结束。
在程序就说明了这个问题。生产者线程生成素数,并将它们放入一个阻塞队列。如果生产者的速度超过了消费者的处理速度,队列将被填满,put方法也会阻塞。当生产者在put方法中阻塞时,如果消费者希望取消生产者任务,那么将会发生什么情况呢??它可以调用cancel方法来设置cancalled标志,但此时生产者却永远不能检测这个标志,因为它无法从阻塞的put方法中恢复过来(因为消费者此时已经停止从队列中取出素数,所以put方法将一直保持阻塞状态)。
并发编程实战:取消和关闭相关推荐
- Java高并发编程:取消和关闭
Java没有提供任何机制来安全地终止线程,但是它提供了中断(Interruption).这是一种协作机制,能够使一个线程终止另一个线程当前的工作. 在对一个线程对象调用Thread.interrupt ...
- Java并发编程实战————Executor框架与任务执行
引言 本篇博客介绍通过"执行任务"的机制来设计应用程序时需要掌握的一些知识.所有的内容均提炼自<Java并发编程实战>中第六章的内容. 大多数并发应用程序都是围绕&qu ...
- JAVA并发编程实战-任务执行
目录 思维导图 1 在线程中执行任务 1.1 顺序执行任务 1.2 显式的为任务创建线程 1.3 无限制创建线程的缺点 2 Executor框架 2.1 使用Executor实现WebServer 2 ...
- 《Java 并发编程实战》--读书笔记
Java 并发编程实战 注: 极客时间<Java 并发编程实战>–读书笔记 GitHub:https://github.com/ByrsH/Reading-notes/blob/maste ...
- aqs clh java_【Java并发编程实战】—– AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...
- c++并发编程实战_Java 并发编程实战:JAVA中断线程几种基本方法
一个多线程Java程序,只有当其全部线程执行结束时(更具体地说,是所有非守护线程结束或者某个线程调用system.exit()方法的时候) ,才会结束运行.有时,为了终止程序或者取消一个线程对象所执行 ...
- Java并发编程实战_不愧是领军人物!这种等级的“Java并发编程宝典”谁能撰写?...
前言 大家都知道并发编程技术就是在同一个处理器上同时的去处理多个任务,充分的利用到处理器的每个核心,最大化的发挥处理器的峰值性能,这样就可以避免我们因为性能而产生的一些问题. 大厂的核心负载肯定是非常 ...
- java并发编程实战学习(3)--基础构建模块
转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...
- Java并发编程实战--FutureTask
FutureTask也可以用作闭锁.(FutureTask实现了Future语义,表示一种抽象的可生成结果的计算.FutureTask表示的计算是通过Callable来实现的,相当于一种可生成结果的R ...
- java并发编程实战(二)
java并发编程中常常会用到两种容器来存放一些数据,这些数据需要保证能在多线程下正常访问.常见的容器分为两类:同步容器和并发容器.在java并发编程实战一书中的第五章也有讲解. 什么是同步容器以及优劣 ...
最新文章
- jenkins ssl证书报错问题解决
- Android 调试 Release 包(debuggable)
- 深度学习之递归神经网络(Recurrent Neural Network,RNN)
- 新云网、5G、Wi-Fi 6 Plus,探秘2021通信展上的锐捷网络黑科技
- Spring+Hessian搭建远程方法调用
- 通过Windows远程桌面连接将远程文件传输至本地
- 错误消息:'events' 为空或不是对象
- linux内核调用串口,linux驱动之串口驱动框架
- Linux日志管理工具 journalctl
- vmware 7.0 序列号_更改solidworks序列号及修改安装
- 第5章 电容元件与电感元件
- swift生成二维码
- 目标检测中region proposal的作用?
- Unity3D游戏制作学习记录03——丛林战争
- Skeleton Screen -- 骨架屏
- 计算机技术考研科目大纲,2017计算机考研大纲:计算机大纲文字完整版
- 在那山的这边海的那边有一群程序员
- docker kong环境部署
- 电子元器件贸易行业仓库管理难?全流程条码管理轻松解决
- 大端字节序码流中取出2字节_字节码忍者的秘密