中断线程
在 run() 方法中,如果语句执行到了最会一句,或是遇到 return 方法,或是方法中出现了没有被捕获的异常,run() 方法将会执行结束。在java中,Thread中的interrupt() 方法被调用时,线程中断状态将被置位,由于线程在运行期间,会不断的检测这个状态位,以判断程序是否被中断。
检测线程是否被中断
在实际开发中,要判断中断状态位是否被置位,首先使用静态方法 Thread.currentThread() 方法来获取当前线程,在调用 interrupted() 方法来判断中断位的状态。如下:
  1. while (!Thread.currentThread().interrupted() && more work to do) {}

interrupted 和  isInterrupted  区别

interrupted 是一个静态方法,他检测当前线程是否中断,并且会清除当前线程的中断位。isInterrupted 是一个实例方法,检测线程中断位,不会清除状态位。
如何中断线程
如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。interrupt 不会中断一个正在运行的线程。
要注意的是,中断线程不等于终止线程,interrupt  只是只是改变了线程的状态位,来引起线程的注意或是唤醒沉睡的线程。但是当线程注意到(捕获到InterruptedException异常或是检测到状态位的改变),可以自行决定如何处理该线程,比如,可以让线程捕获异常后继续执行,或是中断线程。
在实际操作中,一般会把线程中断当做线程结束的条件,格式如下:
  1. @Override
  2. public void run() {
  3. while(!Thread.currentThread().isInterrupted() ){
  4. try{
  5. //处理正常的逻辑
  6. Thread.sleep(100);
  7. }catch (InterruptedException e){
  8. //被中断后的进入
  9.  
  10. //由于抛出异常后会把状态位改变,所以这里应该手动改变状态位
  11. Thread.currentThread().interrupt();
  12. }finally{
  13. // 线程结束前的后续操作
  14. }
  15. }
  16. }
一般不会在捕获的异常中不进行任何操作,这样可能会处理不当中断,比如:
  1. @Override
  2. public void run() {
  3. try{
  4. Thread.sleep(100);
  5. }catch (InterruptedException e){ }
  6. }
选择抛出异常,也是很好的选择:

  1. void mySubTask() throws InterruptedException {
  2. ...
  3. sleep(delay);
  4. ...
  5. }
如何中断一个线程
实例一:
  1. public class Example1 implements Runnable{
  2. private float d;
  3. @Override
  4. public void run() {
  5. while(true){
  6. for(int i=0;i<10000000;i++){
  7. d = (float) (d + (Math.PI + Math.E) / d);
  8. }
  9. System.out.println("I'm counting......");
  10. //转让调度器使用权
  11. Thread.yield();
  12. }
  13. }
  14.  
  15. public static void main(String[] args) throws InterruptedException {
  16. Example1 example1 = new Example1();
  17. Thread t1 = new Thread(example1);
  18. t1.start();
  19.  
  20. Thread.sleep(100);
  21.  
  22. System.out.println("开始中断线程。。。。。。");
  23. t1.interrupt();
  24. }
  25. }

输出:

  1. I'm counting......
  2. 开始中断线程。。。。。。
  3. I'm counting......
  4. I'm counting......
  5. I'm counting......
  6. I'm counting......
可以看出来,线程被调用interrupt方法后,并没有被中断,任然在运行,所以说,interrupt 方法并不能是线程终止运行。
要是线程中断运行,有三种方法,抛出Interrupt异常,使用 Thread.interrupted() 不断检查中断状态位,使用信号量进行控制。

方法一:信号量法

  1. class Example2 implements Runnable{
  2.  
  3. public static boolean isLive = true;
  4. float d;
  5. @Override
  6. public void run() {
  7. while(isLive){
  8. for(int i=0;i<10000000;i++){
  9. d = (float) (d + (Math.PI + Math.E) / d);
  10. }
  11. System.out.println("I'm counting......");
  12. //转让调度器使用权
  13. Thread.yield();
  14. }
  15. }
  16.  
  17. public static void main(String[] args) throws InterruptedException {
  18. Example2 e2 = new Example2();
  19. Thread t1 = new Thread(e2);
  20. t1.start();
  21.  
  22. Thread.sleep(100);
  23.  
  24. System.out.println("开始中断线程。。。。。。");
  25.  
  26. //设置改变信号量
  27. e2.isLive = false;
  28. }
  29. }

输出结果:

  1. I'm counting......
  2. 开始中断线程。。。。。。
  3. I'm counting......

方法二:抛出异常法

  1. public class Example1 implements Runnable{
  2.  
  3. private double d = 0.0;
  4. public void run() {
  5. //死循环执行打印"I am running!" 和做消耗时间的浮点计算
  6. try {
  7. while (true) {
  8. System.out.println("I am running!");
  9. for (int i = 0; i < 900000; i++) {
  10. d = d + (Math.PI + Math.E) / d;
  11. }
  12. //休眠一断时间,中断时会抛出InterruptedException
  13. Thread.sleep(50);
  14. }
  15. } catch (InterruptedException e) {
  16. System.out.println("ATask.run() interrupted!");
  17. }
  18. }
  19.  
  20. public static void main(String[] args) throws InterruptedException {
  21. Example1 example1 = new Example1();
  22. Thread t1 = new Thread(example1);
  23. t1.start();
  24.  
  25. Thread.sleep(100);
  26.  
  27. System.out.println("开始中断线程。。。。。。");
  28. t1.interrupt();
  29. }
  30. }

输出结果

  1. I am running!
  2. I am running!
  3. 开始中断线程。。。。。。
  4. ATask.run() interrupted!

方法三:Thread.interrupted()监听

  1. class Example3 implements Runnable {
  2. @Override
  3. public void run() {
  4. while (!Thread.currentThread().interrupted()) {
  5. try {
  6. Thread.sleep(100);
  7. System.out.println("I'm counting......");
  8. } catch (InterruptedException e) {
  9. //设置状态位
  10. Thread.currentThread().interrupt();
  11. }
  12. }
  13. }
  14.  
  15. public static void main(String[] args) throws InterruptedException {
  16. Example3 e = new Example3();
  17. Thread t1 = new Thread(e);
  18. t1.start();
  19.  
  20. Thread.sleep(800);
  21.  
  22. System.out.println("开始中断线程。。。。。。");
  23.  
  24. t1.interrupt();
  25.  
  26. }
  27. }

输出为:

  1. I'm counting......
  2. I'm counting......
  3. I'm counting......
  4. I'm counting......
  5. I'm counting......
  6. I'm counting......
  7. 开始中断线程。。。。。。
被遗弃的stop和suspend
早起的Java版本提供了stop方法来终止一个线程,以及suspend来阻塞一个线程直到另一个线程调用resume来唤醒线程。stop和suspend这两个方法都试图控制给定线程的想行为。
stop 方法试图终止一个线程的执行,包括未执完的run方法,其本身是很不安全的。比如说,当一个线程试图从一个账户转账到另一个账户,一个线程已经把钱取出来了,但是此正好被stop终止了线程,但是钱却没有转到另一个账户。这样的突然终止导致银行对象出于不稳定的状态。虽然此时锁被释放了,但是他的不稳定状态却不能被其他线程看到,这是很危险的。
suspend 方法用来挂起一个锁,虽然不会破坏对象,但是有可能导致死锁。假设如果用suspend方法挂起一个拥有锁的线程,那么,该锁在恢复之前是不可用的。如果此时,调用suspend方法的线程试图获取同一个锁,那么,此时就会出现死锁。

Java中断机制(interrupt)的更多相关文章

  1. 【转】详细分析Java中断机制

    原文地址:http://www.infoq.com/cn/articles/java-interrupt-mechanism 1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制 ...

  2. 详细分析Java中断机制(转)

    1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法 ...

  3. 详细分析Java中断机制-转载

    1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法 ...

  4. 详细分析Java中断机制[转]

    1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法 ...

  5. Java中断机制

    1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法 ...

  6. Java并发(基础知识)—— Java中断机制

    上文讲解了Java线程的创建.启动以及停止,在讲到停止线程时说到了Java中断,Java中断是停止线程的一种协作机制,本文打算对Java中断机制进行详细讲解. 在网上搜索Java中断机制,发现两篇好文 ...

  7. Java Thread.interrupt interrupted

    Java Thread.interrupt @(Base)[JDK, 线程, interrupt] 原文地址,转载请注明 下面这个场景你可能很熟悉,我们调用Thread.sleep(),conditi ...

  8. Java面试-interrupt

    我们都知道,Java中停止一个线程不能用stop,因为stop会瞬间强行停止一个线程,且该线程持有的锁并不能释放.大家多习惯于用interrupt,那么使用它又有什么需要注意的呢? interrupt ...

  9. java中interrupt,interrupted和isInterrupted的区别

    文章目录 isInterrupted interrupted interrupt java中interrupt,interrupted和isInterrupted的区别 前面的文章我们讲到了调用int ...

随机推荐

  1. 电脑IP地址被占用如何释放?

    回车后,关机,等待5分钟左右再开机,就释放掉了.

  2. 用html+css+js做打地鼠小游戏

    html 代码 first.html <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  3. YYModel学习总结YYClassInfo(1)

    OC的run-time 机制,简直像是网络上的猫! 我在开发中很少用到,但是作为iOS开发 人家肯定会问这个东西,所以深入的学习了下. 对于 run-time的入手,YYModel的学习,简直让人美滋 ...

  4. curl命令用于模拟http浏览器发起动作

    1.模拟http浏览器发起访问百度首页的动作 curl  http://www.baidu.com 2.也可以模拟http浏览器发起POST动作,这个在测试后端程序时非常常见.

  5. 1.ElasticSearch介绍及基本概念

    一.ElasticSearch介绍 一个采用RESTful API标准的高扩展性的和高可用性的实时性分析的全文搜索工具 基于Lucene[开源的搜索引擎框架]构建 ElasticSearch是一个面向 ...

  6. win10 UWP Controls by function

    Windows的XAML UI框架提供了很多控件,支持用户界面开发库.其中一些有可视化,一些布局. 一些控件例子:https://github.com/Microsoft/Windows-univer ...

  7. Entity Framework Core 2.0 使用入门

    一.前言 Entity Framework(后面简称EF)作为微软家的ORM,自然而然从.NET Framework延续到了.NET Core.以前我也嫌弃EF太重而不去使用它,但是EF Core(E ...

  8. 【转】C语言中内存分配

    原文:C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要 ...

  9. APUE 4 - 线程<2> : 线程同步

    当控件的多个线程共享统一内存时,我们需要确定各个线程访问到的数据的一致性.在cpu结构中,修改操作由多个内存读写周期(memory cycle),而在这些内存周期之间, 有可能会发生其他线程的内存读操 ...

  10. js math对象总结

    1:  Math 对象用于执行数学任务. 2:Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(), Math.sin() 这样的函数只是函数 3:通过把 ...