`

Java线程学习笔记(四):线程的中断

    博客分类:
  • Java
阅读更多

方法原型:public void interrupt()

方法说明:

  • 中断线程
  • 如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的checkAccess()方法就会被调用,这可能抛出SecurityException
  • 如果线程在调用Object类的wait()、wait(long)或者wait(long, int)方法,或者该类的join()、join(long)、join(long, int)、sleep(long)或者sleep(long, int)方法过程中受阻,则其中断状态将会被清除,它还将抛出一个InterruptedException
  • 如果该线程在可中断的通道(InterruptibleChannel)上I/O操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将受到一个CloseByInterruptException
  • 如果该线程在一个Selector中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的wakeup方法一样
  • 如果以前的条件都没有保存,则该线程的中断状态将被设置

示例1:测试interrupt()方法

public class Hello implements Runnable {
	
	private double d = 0.0;

	public void run() {
		//死循环执行打印“I am running”和消耗时间的浮点数运算
		while (true) {
			System.out.println("I am running!");
			for (int i = 0; i < 900000; i++) {
				d = d + (Math.PI + Math.E) / d;
			}
			//给线程调度器可以调度其它线程的信号
			Thread.yield();
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new Hello());
		
		System.out.println("线程的中断状态1:" + t.isInterrupted());
		t.start();
		t.sleep(100);
		System.out.println("*****************************");
		System.out.println("Interrupted Thread!");
		System.out.println("*****************************");
		t.interrupt();
		System.out.println("线程的中断状态2:" + t.isInterrupted());
	}
}
执行结果 写道
线程的中断状态1:false
I am running!
... ...
I am running!
I am running!
*****************************
Interrupted Thread!
*****************************
线程的中断状态2:true
I am running!
I am running!
... ...

 分析:程序虽然调用了interrupt()方法,但是并没有中断执行,而是继续运行。但是interrupt状态由false变为了true。由此得出结论,线程的“中断”不是让线程停止。

Java中线程的中断(interrupt)只是改变了线程的中断状态,这个中断状态改变后带来的结果,是无法确定的。有时,它更是让停止中的线程继续执行的唯一手段,不但不是让线程停止运行的手段,反而是继续执行线程的手段。

 

离开线程有两种方法:

1、抛出InterruptedException异常

2、用Thread.interrupted()检查是否发生中断

 

示例2:抛出InterruptedException异常

public class Hello implements Runnable {
	
	private double d = 0.0;

	public void run() {
		try {
			//死循环执行打印“I am running”和消耗时间的浮点数运算
			while (true) {
				System.out.println("I am running!");
				for (int i = 0; i < 900000; i++) {
					d = d + (Math.PI + Math.E) / d;
				}
				//休眠一段时间,中断后会抛出InterruptedException异常,
				//当抛出该异常的时候,当前线程的"中断状态"被清除。
				Thread.sleep(50);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new Hello());
		
		System.out.println("线程的中断状态1:" + t.isInterrupted());
		t.start();
		t.sleep(100);
		System.out.println("*****************************");
		System.out.println("Interrupted Thread!");
		System.out.println("*****************************");
		t.interrupt();
		System.out.println("线程的中断状态2:" + t.isInterrupted());
	}
}
执行结果 写道
线程的中断状态1:false
I am running!
I am running!
*****************************
Interrupted Thread!
*****************************
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.test2.Hello.run(Hello.java:16)
at java.lang.Thread.run(Thread.java:744)
线程的中断状态2:false

 分析:如代码及执行结果所示,子线程run()方法中,每执行一次循环体,就会休眠50ms,当主线程执行到t.interrupt()操作的时候,子线程的中断状态将会改变为true,子线程再执行Thread.sleep()方法的时候,会抛出java.lang.InterruptedException异常,此时子线程的中断状态将会被重置,所以在最后的输出中,子线程的中断状态还是false。

特别注意:run()中的try-catch块,必须将整个while循环括在try块中。如果单独只是括sleep()方法,则线程不会被终止,而是继续执行,原因就是sleep()方法抛出的异常已经被捕获了,而这个被捕获的异常并没有影响到后续程序的运行。

 

示例3:用Thread.interrupted()检查是否发生中断

 

public class Hello implements Runnable {
	
	private double d = 0.0;

	public void run() {
		try {
			//判断程序是否发生中断
			while (!Thread.interrupted()) {
				System.out.println("I am running!");
				for (int i = 0; i < 900000; i++) {
					d = d + (Math.PI + Math.E) / d;
				}
				//休眠一段时间,中断后会抛出InterruptedException异常,
				//当抛出该异常的时候,当前线程的"中断状态"被清除。
				Thread.sleep(50);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new Hello());
		
		System.out.println("线程的中断状态1:" + t.isInterrupted());
		t.start();
		t.sleep(100);
		System.out.println("*****************************");
		System.out.println("Interrupted Thread!");
		System.out.println("*****************************");
		t.interrupt();
		System.out.println("线程的中断状态2:" + t.isInterrupted());
	}
}
可能执行结果1 写道
线程的中断状态1:false
I am running!
I am running!
*****************************
Interrupted Thread!
*****************************
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.test2.Hello.run(Hello.java:17)
at java.lang.Thread.run(Thread.java:744)
线程的中断状态2:false
可能执行结果2 写道
线程的中断状态1:false
I am running!
I am running!
*****************************
Interrupted Thread!
*****************************
线程的中断状态2:true
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.test2.Hello.run(Hello.java:17)
at java.lang.Thread.run(Thread.java:744)

 分析:

  1. isInterrupted():测试线程是否中断。线程的“中断状态”不受方法的影响。在新版的jre(7)中该结论需要斟酌,个人理解如果没有错的话,isInterrupted()也可能会影响线程的中断状态。
  2. interrupted():测试当前线程是否已经中断。线程的“中断状态”由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回false(在第一次调用已经清除了其中断状态之后,且第二次调用检查完中断状态前,当前线程再次中断的情况除外)。详见以下补充示例。
  3. 多执行几次,会出现两个截然不同的结果(最后一次测试中断状态的结果完全相反)。个人理解,由于sleep()方法执行的时间点不同,从而影响了该结果。

补充示例:interrupted()方法验证

public class Hello implements Runnable {
	
	private double d = 0.0;

	public void run() {
		//判断程序是否发生中断,第一次调用interrupted()方法
		while (!Thread.interrupted()) {
			System.out.println("I am running!");
			for (int i = 0; i < 900000; i++) {
				d = d + (Math.PI + Math.E) / d;
			}
		}
		System.out.println("第二次调用Thread.interrupted()方法:" + Thread.interrupted());
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new Hello());
		
		System.out.println("线程的中断状态1:" + t.isInterrupted());
		t.start();
		t.sleep(100);
		System.out.println("*****************************");
		System.out.println("Interrupted Thread!");
		System.out.println("*****************************");
		t.interrupt();
		System.out.println("线程的中断状态2:" + t.isInterrupted());
	}
}
执行结果 写道
线程的中断状态1:false
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
*****************************
Interrupted Thread!
*****************************
线程的中断状态2:true
第二次调用Thread.interrupted()方法:false

 

 

 注:本文源自互联网,经过查阅网上资料整理而成,如涉及到他人整理的成果,在此表示感谢。由于涉及到的参考文章比较多,在此就不再一一列举。

本文是目前个人理解的结果,仅供参考,如后续发现问题,本人会进行相应的更正,也欢迎各位对Java线程感兴趣的朋友或者前辈进行指正。

分享到:
评论

相关推荐

    java多线程笔记

    Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...

    java线程学习笔记

    java线程学习笔记

    java多线程编程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...

    Java多线程编程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...

    多线程学习笔记

    多线程学习笔记,通过平时的学习所做的一些笔记,希望对广大同仁有所帮助

    java学习笔记2(多线程)

    java学习笔记2(多线程)java学习笔记2(多线程)

    Java 线程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...

    JAVA 多线程学习笔记

    NULL 博文链接:https://baobeituping.iteye.com/blog/1190260

    java 线程 dump 分析工具 2.3.3

    java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    如果你想使用Java,就必须学习线程。 本书的新版本展示了如何利用Java线程工具的全部优势,并介绍了JDK 2线程接口中的最新变化。你将学习如何使用线程来提高效率,如何有效地使用它们,以及如何避免常见的错误。...

    java线程 线程学习资料 java线程教程

    java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...

    java 线程总结笔记

    花费了一上午的时候 写了一些demo。认识到四种线程池的区别。上传到csdn 供以后学习

    java线程详解

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程状态的转换 Java线程:线程的同步与锁 一、同步问题提出 二、同步和锁定 三、静态方法同步 四、如果线程不能不能获得锁会怎么样 五、何时需要同步...

    Java多线程学习Java多线程学习Java多线程学习Java多线程学习.txt

    Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java...

    Java多线程笔记

    多线程学习笔记,好资源。包括线程基础等知识多线程学习笔记,好资源。包括线程基础等知识

Global site tag (gtag.js) - Google Analytics