当前位置: 首页 > news >正文

java取消线程实例

本文展示一个常见的取消线程的方法。

错误实例

class BrokenPrimeProducer extends Thread {
    private final BlockingQueue<BigInteger> queue;
    private volatile boolean cancelled = false;

    BrokenPrimeProducer(BlockingQueue<BigInteger> queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            BigInteger p = BigInteger.ONE;
            while (!cancelled){
                queue.put(p = p.nextProbablePrime());
            }    
        } catch (InterruptedException consumed) {
        }
    }

    public void cancel() {
        cancelled = true;
    }
}

这里试图用一个标志来跳出while循环,理论上貌似可行,但是这里使用的是阻塞的操作,那么就出现一种场景,线程永远阻塞在put方法,根本就没来得及下个循环去判断cancelled这个条件,造成永远无法停止掉线程。

正确方法

通过中断来取消线程。

public class PrimeProducer extends Thread {
    private final BlockingQueue<BigInteger> queue;

    PrimeProducer(BlockingQueue<BigInteger> queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            BigInteger p = BigInteger.ONE;
            while (!Thread.currentThread().isInterrupted()){
                queue.put(p = p.nextProbablePrime());
            }    
        } catch (InterruptedException consumed) {
            /* Allow thread to exit */
        }
    }

    public void cancel() {
        interrupt();
    }
}

这里的关键是queue的put操作能够响应interrupt方法,抛出InterruptedException,倒不是因为while条件里头的isInterrupted,这里while条件换成boolean可以照样可以。

小结

调用interrupt并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。对中断操作的正确理解是:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。

有些方法,例如wait、sleep和join等,将严格地处理这种请求,当它们收到中断请求或者在开始执行时发现某个已被设置好的中断状态时,将抛出一个异常。设计良好的方法可以完全忽略这种请求,只要它们能使调用代码对中断请求进行某种处理。

设计糟糕的方法可能会屏蔽中断请求,从而导致调用栈中的其他代码无法对中断请求作出响应。在使用静态的interrupted时应该小心,因为它会清除当前线程的中断状态。如果在调用interrupted时返回了true,那么除非你想屏蔽这个中断,否则必须对它进行处理—可以抛出InterruptedException,或者通过再次调用interrupt来恢复中断状态。

相关文章:

  • JqGrid
  • 【React系列】如何构建React应用程序
  • 【逻辑题】舅舅问题
  • 如何开发主控台部件
  • 优秀网站分享
  • 工具收藏
  • MongoDB 学习笔记之 WriteConcern
  • js new Date()的兼容性问题
  • Jedox Cloud安全可升级自助式商业情报
  • [bzoj1006]: [HNOI2008]神奇的国度(最大势算法)
  • 由插件封装引出的一丢丢思考
  • 背水一战 Windows 10 (53) - 控件(集合类): ItemsControl 的布局控件 - ItemsStackPanel, ItemsWrapGrid...
  • 三网卡服务器 配置三线三IP linux策略路由
  • Oracle 插入时间时 报错:ORA-01861: 文字与格式字符串不匹配 的解决办法
  • Entity Framework中的字符串插值引发担忧
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • Android框架之Volley
  • bearychat的java client
  • centos安装java运行环境jdk+tomcat
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • go语言学习初探(一)
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • JSDuck 与 AngularJS 融合技巧
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • LeetCode算法系列_0891_子序列宽度之和
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • nginx 负载服务器优化
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Spring Boot MyBatis配置多种数据库
  • 阿里云应用高可用服务公测发布
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 盘点那些不知名却常用的 Git 操作
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 设计模式(12)迭代器模式(讲解+应用)
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 算法之不定期更新(一)(2018-04-12)
  • 我从编程教室毕业
  • 我的面试准备过程--容器(更新中)
  • 小程序开发中的那些坑
  • 再次简单明了总结flex布局,一看就懂...
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • ​业务双活的数据切换思路设计(下)
  • !$boo在php中什么意思,php前戏
  • #Linux(Source Insight安装及工程建立)
  • (6)添加vue-cookie
  • (C#)获取字符编码的类
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (安卓)跳转应用市场APP详情页的方式
  • (待修改)PyG安装步骤
  • (二)丶RabbitMQ的六大核心
  • (分布式缓存)Redis分片集群
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (实战篇)如何缓存数据