使用interrupt()中断线程

当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回。这里需要注意的是,如果只是单纯的调用interrupt()方法,线程并没有实际被中断,会继续往下执行。

下面一段代码演示了休眠线程的中断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
publicclass SleepInterrupt extendsObject implementsRunnable{
    publicvoid run(){
        try{
            System.out.println("in run() - about to sleep for 20 seconds");
            Thread.sleep(20000);
            System.out.println("in run() - woke up");
        }catch(InterruptedException e){
            System.out.println("in run() - interrupted while sleeping");
            //处理完中断异常后,返回到run()方法人口,
            //如果没有return,线程不会实际被中断,它会继续打印下面的信息
            return
        }
        System.out.println("in run() - leaving normally");
    }
    publicstatic void main(String[] args) {
        SleepInterrupt si = newSleepInterrupt();
        Thread t = newThread(si);
        t.start();
        //主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
        try{
            Thread.sleep(2000);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("in main() - interrupting other thread");
        //中断线程t
        t.interrupt();
        System.out.println("in main() - leaving");
    }
}

运行结果如下:

主线程启动新线程后,自身休眠2秒钟,允许新线程获得运行时间。新线程打印信息“about to sleep for 20 seconds”后,继而休眠20秒钟,大约2秒钟后,main线程通知新线程中断,那么新线程的20秒的休眠将被打断,从而抛出InterruptException异常,执行跳转到catch块,打印出“interrupted while sleeping”信息,并立即从run()方法返回,然后消亡,而不会打印出catch块后面的“leaving normally”信息。
请注意:由于不确定的线程规划,上图运行结果的后两行可能顺序相反,这取决于主线程和新线程哪个先消亡。但前两行信息的顺序必定如上图所示。
另外,如果将catch块中的return语句注释掉,则线程在抛出异常后,会继续往下执行,而不会被中断,从而会打印出”leaving normally“信息。

待决中断

在上面的例子中,sleep()方法的实现检查到休眠线程被中断,它会相当友好地终止线程,并抛出InterruptedException异常。另外一种情况,如果线程在调用sleep()方法前被中断,那么该中断称为待决中断,它会在刚调用sleep()方法时,立即抛出InterruptedException异常。

下面的代码演示了待决中断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
publicclass PendingInterrupt extendsObject {
    publicstatic void main(String[] args){
        //如果输入了参数,则在mian线程中中断当前线程(亦即main线程)
        if( args.length > 0){
            Thread.currentThread().interrupt();
        }
        //获取当前时间
        longstartTime = System.currentTimeMillis();
        try{
            Thread.sleep(2000);
            System.out.println("was NOT interrupted");
        }catch(InterruptedException x){
            System.out.println("was interrupted");
        }
        //计算中间代码执行的时间
        System.out.println("elapsedTime="+ ( System.currentTimeMillis() - startTime));
    }
}

如果PendingInterrupt不带任何命令行参数,那么线程不会被中断,最终输出的时间差距应该在2000附近(具体时间由系统决定,不精确),如果PendingInterrupt带有命令行参数,则调用中断当前线程的代码,但main线程仍然运行,最终输出的时间差距应该远小于2000,因为线程尚未休眠,便被中断,因此,一旦调用sleep()方法,会立即打印出catch块中的信息。执行结果如下:

这种模式下,main线程中断它自身。除了将中断标志(它是Thread的内部标志)设置为true外,没有其他任何影响。线程被中断了,但main线程仍然运行,main线程继续监视实时时钟,并进入try块,一旦调用sleep()方法,它就会注意到待决中断的存在,并抛出InterruptException。于是执行跳转到catch块,并打印出线程被中断的信息。最后,计算并打印出时间差。

使用isInterrupted()方法判断中断状态

可以在Thread对象上调用isInterrupted()方法来检查任何线程的中断状态。这里需要注意:线程一旦被中断,isInterrupted()方法便会返回true,而一旦sleep()方法抛出异常,它将清空中断标志,此时isInterrupted()方法将返回false。
下面的代码演示了isInterrupted()方法的使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
publicclass InterruptCheck extendsObject{
    publicstatic void main(String[] args){
        Thread t = Thread.currentThread();
        System.out.println("Point A: t.isInterrupted()=" + t.isInterrupted());
        //待决中断,中断自身
        t.interrupt();
        System.out.println("Point B: t.isInterrupted()=" + t.isInterrupted());
        System.out.println("Point C: t.isInterrupted()=" + t.isInterrupted());
        try{
            Thread.sleep(2000);
            System.out.println("was NOT interrupted");
        }catch( InterruptedException x){
            System.out.println("was interrupted");
        }
        //抛出异常后,会清除中断标志,这里会返回false
        System.out.println("Point D: t.isInterrupted()=" + t.isInterrupted());
    }
}

运行结果如下:

使用Thread.interrupted()方法判断中断状态

可以使用Thread.interrupted()方法来检查当前线程的中断状态(并隐式重置为false)。又由于它是静态方法,因此不能在特定的线程上使用,而只能报告调用它的线程的中断状态,如果线程被中断,而且中断状态尚不清楚,那么,这个方法返回true。与isInterrupted()不同,它将自动重置中断状态为false,第二次调用Thread.interrupted()方法,总是返回false,除非中断了线程。

如下代码演示了Thread.interrupted()方法的使用:

1
2
3
4
5
6
7
8
9
10
11
publicclass InterruptReset extendsObject {
    publicstatic void main(String[] args) {
        System.out.println(
            "Point X: Thread.interrupted()=" + Thread.interrupted());
        Thread.currentThread().interrupt();
        System.out.println(
            "Point Y: Thread.interrupted()=" + Thread.interrupted());
        System.out.println(
            "Point Z: Thread.interrupted()=" + Thread.interrupted());
    }
}

运行结果如下:

从结果中可以看出,当前线程中断自身后,在Y点,中断状态为true,并由Thread.interrupted()自动重置为false,那么下次调用该方法得到的结果便是false。

补充

这里补充下yield和join方法的使用。
join方法用线程对象调用,如果在一个线程A中调用另一个线程B的join方法,线程A将会等待线程B执行完毕后再执行。
yield可以直接用Thread类调用,yield让出CPU执行权给同等级的线程,如果没有相同级别的线程在等待CPU的执行权,则该线程继续执行。
from: http://www.importnew.com/20527.html
原文出处: 兰亭风雨

Java并发编程(2):线程中断(含代码)相关推荐

  1. JAVA并发编程3_线程同步之synchronized关键字

    在上一篇博客里讲解了JAVA的线程的内存模型,见:JAVA并发编程2_线程安全&内存模型,接着上一篇提到的问题解决多线程共享资源的情况下的线程安全问题. 不安全线程分析 public clas ...

  2. [转]Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  3. Java并发编程:线程池的使用

    在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...

  4. 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )

    文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...

  5. java并发编程与线程安全

    2019独角兽企业重金招聘Python工程师标准>>> 什么是线程安全 如果对象的状态变量(对象的实例域.静态域)具有可变性,那么当该对象被多个线程共享时就的考虑线程安全性的问题,否 ...

  6. Java并发编程:线程的同步

    <?xml version="1.0" encoding="utf-8"?> Java并发编程:线程的同步 Java并发编程:线程的同步 Table ...

  7. Java并发编程一线程池简介

    推荐:Java并发编程汇总 Java并发编程一线程池简介 为什么我们需要使用线程池? 我们知道线程是一种比较昂贵的资源,我们通过程序每创建一个线程去执行,其实操作系统都会对应地创建一个线程去执行我们的 ...

  8. Java并发编程一线程池的五种状态

    推荐:Java并发编程汇总 Java并发编程一线程池的五种状态 原文地址 Java多线程线程池(4)–线程池的五种状态 正文 线程池的5种状态:Running.ShutDown.Stop.Tidyin ...

  9. 【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )

    文章目录 前言 一.线程池示例 二.newCachedThreadPool 线程池示例 三.newFixedThreadPool 线程池示例 三.newSingleThreadExecutor 线程池 ...

  10. (转)Java并发编程:线程池的使用

    背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...

最新文章

  1. C#拾遗系列(9):继承、接口、扩展方法、分部类、类操作、Ref and Out、可空类型...
  2. 方舟服务器如何修改恐龙,方块方舟人物及驯养恐龙属性修改教程 人物属性怎么修改_游侠网...
  3. csdn博客怎么修改字体的大小和颜色
  4. 智能合约重构社会契约 (3)智能合约的自动触发
  5. Python: 字符串中嵌入变量
  6. vue/cli 3.0 font-size随屏幕大小变化而变化 rem设置
  7. linux系统怎么安装pr,Linux安装后的配置
  8. 项目优化到一半还是崩了,新同事换了一套调优方案,全体颤抖。。。
  9. Hadoop生态圈-Flume的组件之sink处理器
  10. 曾经的8848,远离真实的代价
  11. canoe开发从入门到精通_后端java开发工程师学习路线
  12. AJAX和select,绑定值,动态加载select的Item值,设置所选的值 (全都是客户端控件)...
  13. tinycc update VERSION to 0.9.27
  14. matlab的otdr仿真,otdr测试曲线生成软件-OTDR测试曲线图仿真软件TrcView 4.0 官方免费版 - 河东下载站...
  15. 【Unity】【Odin Inspector】关于AOT Generation
  16. leetcode简单之1076.项目员工II
  17. 2022年TikTok的9个变现模式
  18. 机器学习之中文处理:文言文还是白话文
  19. 深度学习图像分类(六):Stochastic_Depth_Net
  20. Robert Marino:欧洲创新的代表性不足,量子计算或能破局

热门文章

  1. linux下的time函数们
  2. 2020 年软件开发趋势预测,Java 将占主导,Python 将要吞噬世界
  3. 大数据分析币圈动态: ETH、BTC、BCH每秒交易均呈负增长! 以太坊网络传播时间再缩短
  4. 2017年度盘点:15个最流行的GitHub机器学习项目 By 机器之心2017年12月21日 15:23 在本文中,作者列出了 2017 年 GitHub 平台上最为热门的知识库,囊括了数据科学、机
  5. 二、【绪论】算法和算法评价
  6. 深入理解分布式技术 - 微服务为什么需要API 网关
  7. Spring-AOP 自动创建代理之AnnotationAwareAspectJAutoProxyCreator
  8. Linux内核链表之共享双链表
  9. php访问数组用引号_php双引号中访问数组元素报错如何解决
  10. qt编写activex_Qt中使用ActiveX(一)