资讯专栏INFORMATION COLUMN

java取消线程实例

andot / 569人阅读

摘要:正确方法通过中断来取消线程。小结调用并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。在使用静态的时应该小心,因为它会清除当前线程的中断状态。

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

错误实例
class BrokenPrimeProducer extends Thread {
    private final BlockingQueue queue;
    private volatile boolean cancelled = false;

    BrokenPrimeProducer(BlockingQueue 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 queue;

    PrimeProducer(BlockingQueue 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来恢复中断状态。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70433.html

相关文章

  • Nacos系列:Nacos的Java SDK使用

    摘要:发布配置支持程序自动发布配置,创建和修改配置使用同一个方法,配置不存在则创建配置已存在则更新。示例源码项目代码已上传至码云和上,欢迎下载学习参考资料用户指南的推荐阅读系列欢迎来到的世界系列基于的注册中心系列基于的配置中心 Maven依赖 Nacos提供完整的Java SDK,便于配置管理和服务发现及管理,以 Nacos-0.8.0 版本为例 添加Maven依赖: com.al...

    LinkedME2016 评论0 收藏0
  • Java线程编程基础——Thread 类

    摘要:程序执行时,至少会有一个线程在运行,这个运行的线程被称为主线程。程序的终止是指除守护线程以外的线程全部终止。多线程程序由多个线程组成的程序称为多线程程序。线程休眠期间可以被中断,中断将会抛出异常。 线程 我们在阅读程序时,表面看来是在跟踪程序的处理流程,实际上跟踪的是线程的执行。 单线程程序 在单线程程序中,在某个时间点执行的处理只有一个。 Java 程序执行时,至少会有一个线程在运行...

    zhoutk 评论0 收藏0
  • Java线程-Callable和Future

    摘要:类提供了一些有用的方法在线程池中执行内的任务。在线程池提交任务后返回了一个对象,使用它可以知道任务的状态和得到返回的执行结果。 Callable和Future出现的原因 创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达...

    seasonley 评论0 收藏0
  • Java NIO之Selector(选择器)

    摘要:抽象类有一个方法用于使通道处于阻塞模式或非阻塞模式。注意抽象类的方法是由抽象类实现的,都是直接继承了抽象类。大家有兴趣可以看看的源码,各种抽象类和抽象类上层的抽象类。 历史回顾: Java NIO 概览 Java NIO 之 Buffer(缓冲区) Java NIO 之 Channel(通道) 其他高赞文章: 面试中关于Redis的问题看这篇就够了 一文轻松搞懂redis集群原理及搭建...

    xiaokai 评论0 收藏0
  • Java8的CompletableFuture进阶之道

    摘要:方法接收的是的实例,但是它没有返回值方法是函数式接口,无参数,会返回一个结果这两个方法是的升级,表示让任务在指定的线程池中执行,不指定的话,通常任务是在线程池中执行的。该的接口是在线程使用旧的接口,它不允许返回值。 简介 作为Java 8 Concurrency API改进而引入,本文是CompletableFuture类的功能和用例的介绍。同时在Java 9 也有对Completab...

    SunZhaopeng 评论0 收藏0

发表评论

0条评论

andot

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<