Java多线程系列--“基础篇”09之 interrupt()和线程终止方式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Java多线程系列--“基础篇”09之 interrupt()和线程终止方式

概要

本章,会对线程的interrupt()中断和终止方式进行介绍。涉及到的内容包括:
1. interrupt()说明
2. 终止线程的方式
  2.1 终止处于“阻塞状态”的线程
  2.2 终止处于“运行状态”的线程
3. 终止线程的示例
4. interrupted() 和 isInterrupted()的区别

转载请注明出处:http://www.cnblogs.com/skywang12345/p/3479949.html

1. interrupt()说明

在介绍终止线程的方式之前,有必要先对interrupt()进行了解。
关于interrupt(),java的djk文档描述如下:http://docs.oracle.com/javase/7/docs/api/

  • interrupt()的作用是中断本线程。
  • 本线程中断自己是被允许的;其它线程调用本线程的interrupt()方法时,会通过checkAccess()检查权限。这有可能抛出SecurityException异常。
  • 如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除并且会收到一个InterruptedException异常。例如,线程通过wait()进入阻塞状态,此时通过interrupt()中断该线程;调用interrupt()会立即将线程的中断标记设为“true”,但是由于线程处于阻塞状态,所以该“中断标记”会立即被清除为“false”,同时,会产生一个InterruptedException的异常。
  • 如果线程被阻塞在一个Selector选择器中,那么通过interrupt()中断它时;线程的中断标记会被设置为true,并且它会立即从选择操作中返回。
  • 如果不属于前面所说的情况,那么通过interrupt()中断线程时,它的中断标记会被设置为“true”。
  • 中断一个“已终止的线程”不会产生任何操作。

2. 终止线程的方式

Thread中的stop()和suspend()方法,由于固有的不安全性,已经建议不再使用!
下面,我先分别讨论线程在“阻塞状态”和“运行状态”的终止方式,然后再总结出一个通用的方式。

2.1 终止处于“阻塞状态”的线程

通常,我们通过“中断”方式终止处于“阻塞状态”的线程。
当线程由于被调用了sleep(), wait(), join()等方法而进入阻塞状态;若此时调用线程的interrupt()将线程的中断标记设为true。由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常。将InterruptedException放在适当的位置就能终止线程,形式如下:

@Override
public void run() {try {while (true) {// 执行任务...}} catch (InterruptedException ie) {  // 由于产生InterruptedException异常,退出while(true)循环,线程终止!}
}

说明:在while(true)中不断的执行任务,当线程处于阻塞状态时,调用线程的interrupt()产生InterruptedException中断。中断的捕获在while(true)之外,这样就退出了while(true)循环!
注意:对InterruptedException的捕获务一般放在while(true)循环体的外面,这样,在产生异常时就退出了while(true)循环。否则,InterruptedException在while(true)循环体之内,就需要额外的添加退出处理。形式如下

@Override
public void run() {while (true) {try {// 执行任务...} catch (InterruptedException ie) {  // InterruptedException在while(true)循环体内。// 当线程产生了InterruptedException异常时,while(true)仍能继续运行!需要手动退出break;}}
}

说明:上面的InterruptedException异常的捕获在whle(true)之内。当产生InterruptedException异常时,被catch处理之外,仍然在while(true)循环体内;要退出while(true)循环体,需要额外的执行退出while(true)的操作。

2.2 终止处于“运行状态”的线程

通常,我们通过“标记”方式终止处于“运行状态”的线程。其中,包括“中断标记”和“额外添加标记”。
(01) 通过“中断标记”终止线程。
形式如下:

@Override
public void run() {while (!isInterrupted()) {// 执行任务...}
}

说明:isInterrupted()是判断线程的中断标记是不是为true。当线程处于运行状态,并且我们需要终止它时;可以调用线程的interrupt()方法,使用线程的中断标记为true,即isInterrupted()会返回true。此时,就会退出while循环。
注意:interrupt()并不会终止处于“运行状态”的线程!它会将线程的中断标记设为true。

(02) 通过“额外添加标记”。
形式如下:

private volatile boolean flag= true;
protected void stopTask() {flag = false;
}@Override
public void run() {while (flag) {// 执行任务...}
}

说明:线程中有一个flag标记,它的默认值是true;并且我们提供stopTask()来设置flag标记。当我们需要终止该线程时,调用该线程的stopTask()方法就可以让线程退出while循环。
注意:将flag定义为volatile类型,是为了保证flag的可见性。即其它线程通过stopTask()修改了flag之后,本线程能看到修改后的flag的值。

综合线程处于“阻塞状态”和“运行状态”的终止方式,比较通用的终止线程的形式如下:

@Override
public void run() {try {// 1. isInterrupted()保证,只要中断标记为true就终止线程。while (!isInterrupted()) {// 执行任务...}} catch (InterruptedException ie) {  // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。}
}

3. 终止线程的示例

interrupt()常常被用来终止“阻塞状态”线程。参考下面示例:

// Demo1.java的源码
class MyThread extends Thread {public MyThread(String name) {super(name);}@Overridepublic void run() {try {  int i=0;while (!isInterrupted()) {Thread.sleep(100); // 休眠100msi++;System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  }} catch (InterruptedException e) {  System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  }}
}public class Demo1 {public static void main(String[] args) {  try {  Thread t1 = new MyThread("t1");  // 新建“线程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  t1.start();                      // 启动“线程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  // 主线程休眠300ms,然后主线程给t1发“中断”指令。Thread.sleep(300);t1.interrupt();System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");// 主线程休眠300ms,然后查看t1的状态。Thread.sleep(300);System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");} catch (InterruptedException e) {  e.printStackTrace();}} 
}
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.

结果说明
(01) 主线程main中通过new MyThread("t1")创建线程t1,之后通过t1.start()启动线程t1。
(02) t1启动之后,会不断的检查它的中断标记,如果中断标记为“false”;则休眠100ms。
(03) t1休眠之后,会切换到主线程main;主线程再次运行时,会执行t1.interrupt()中断线程t1。t1收到中断指令之后,会将t1的中断标记设置“false”,而且会抛出InterruptedException异常。在t1的run()方法中,是在循环体while之外捕获的异常;因此循环被终止。

我们对上面的结果进行小小的修改,将run()方法中捕获InterruptedException异常的代码块移到while循环体内。

// Demo2.java的源码
class MyThread extends Thread {public MyThread(String name) {super(name);}@Overridepublic void run() {int i=0;while (!isInterrupted()) {try {Thread.sleep(100); // 休眠100ms} catch (InterruptedException ie) {  System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  }i++;System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  }}
}public class Demo2 {public static void main(String[] args) {  try {  Thread t1 = new MyThread("t1");  // 新建“线程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  t1.start();                      // 启动“线程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  // 主线程休眠300ms,然后主线程给t1发“中断”指令。Thread.sleep(300);t1.interrupt();System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");// 主线程休眠300ms,然后查看t1的状态。Thread.sleep(300);System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");} catch (InterruptedException e) {  e.printStackTrace();}} 
}
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (RUNNABLE) loop 3
t1 (RUNNABLE) loop 4
t1 (RUNNABLE) loop 5
t1 (TIMED_WAITING) is interrupted now.
t1 (RUNNABLE) loop 6
t1 (RUNNABLE) loop 7
t1 (RUNNABLE) loop 8
t1 (RUNNABLE) loop 9
...

结果说明
程序进入了死循环!
为什么会这样呢?这是因为,t1在“等待(阻塞)状态”时,被interrupt()中断;此时,会清除中断标记[即isInterrupted()会返回false],而且会抛出InterruptedException异常[该异常在while循环体内被捕获]。因此,t1理所当然的会进入死循环了。
解决该问题,需要我们在捕获异常时,额外的进行退出while循环的处理。例如,在MyThread的catch(InterruptedException)中添加break 或 return就能解决该问题。

下面是通过“额外添加标记”的方式终止“状态状态”的线程的示例:

// Demo3.java的源码
class MyThread extends Thread {private volatile boolean flag= true;public void stopTask() {flag = false;}public MyThread(String name) {super(name);}@Overridepublic void run() {synchronized(this) {try {int i=0;while (flag) {Thread.sleep(100); // 休眠100msi++;System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  }} catch (InterruptedException ie) {  System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  }}  }
}public class Demo3 {public static void main(String[] args) {  try {  MyThread t1 = new MyThread("t1");  // 新建“线程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  t1.start();                      // 启动“线程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  // 主线程休眠300ms,然后主线程给t1发“中断”指令。Thread.sleep(300);t1.stopTask();System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");// 主线程休眠300ms,然后查看t1的状态。Thread.sleep(300);System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");} catch (InterruptedException e) {  e.printStackTrace();}} 
}
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) loop 3
t1 (TERMINATED) is interrupted now.

4. interrupted() 和 isInterrupted()的区别

最后谈谈 interrupted() 和 isInterrupted()。
interrupted() 和 isInterrupted()都能够用于检测对象的“中断标记”。
区别是,interrupted()除了返回中断标记之外,它还会清除中断标记(即将中断标记设为false);而isInterrupted()仅仅返回中断标记。

 

 

 

 

转载于:https://my.oschina.net/LucasZhu/blog/1529532

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac活动监视器_什么是活动监视器?

mac活动监视器活动监控 (Activity Monitor) Apple OS X provides the services of which one of them is Activity Monitor. Activity Monitor is used to monitor the activities of computer like active processes, processor load, applications that are running, and the…

concurrent包下的Exchanger练习

Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。 当线程A调用Exchange对象的exchange()方法后,他会陷入阻塞状态,直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据…

Python默认参数

Python | 默认参数 (Python | default parameters) A default parameter is a value provided in a function declaration that is automatically assigned by the compiler if the caller of the function doesnt provide a value for the parameter with the default value. …

最长公共前缀_最长的公共前缀

最长公共前缀Problem statement: 问题陈述: Write a function to find the longest common prefix string amongst an array of strings. 编写函数以在字符串数组中找到最长的公共前缀字符串 。 If there is no common prefix, return an empty string "&quo…

物联网听起来像是一个和互联网不同的网,万物互联又把网给弄丢了,正向我们扑面而来的是万物互联网。...

物联网听起来像是一个和互联网不同的网,"万物互联"又把"网"给弄丢了,正向我们扑面而来的是"万物互联网"。转载于:https://www.cnblogs.com/beingonline/p/7484135.html

sdram trp_TRP的完整形式是什么?

sdram trpTRP:电视收视点 (TRP: Television Rating Point) TRP is an abbreviation of "Television Rating Point". TRP是“电视评分点”的缩写 。 It is a system or standard of measurement which signifies the demand and popularity of a televisi…

Controller计算值传到jsp页面,用session传值

HttpSession session request.getSession(); session.setAttribute("key",value); jap 用 ${key}来接收该值 转载于:https://www.cnblogs.com/douder/p/7484491.html

CBT的完整形式是什么?

CBT:基于计算机的培训 (CBT: Computer Based Training) CBT is an abbreviation of "Computer-based training". CBT是“基于计算机的培训”的缩写 。 It is a training program which entails the use of a personal system or networked computer. The…

论道社会化商业

主持人 用友优普副总裁傅毅: 谢谢各位嘉宾,我们会留一些时间让在座的嘉宾提问。请各位嘉宾用一个非常简单的一句话,或者几个关键词,总结一下你认为的社会化商业是什么? 用友优普执行总裁 徐洋: 社会化商业为…

CChelper彩虹SDK可视远程客服解决方案

本文讲的是 : CChelper彩虹SDK可视远程客服解决方案 , 在智能生态产业链中,智能硬件终端是把握消费者的直接环节,随着物联网时代迈向成熟,智能家居领域的硬件逐渐成为智能硬件终端的主角。目前的市场环境下,智能家居领域的自身硬…

matlab 简介_MATLAB简介

matlab 简介MATLAB简介 (MATLAB Introduction) MATLAB was designed by Cleve Moler for his student in 1970s but after some time jack little, an engineer realized its potential and rewrote it at the MathWorks, and it was rewritten in C language by the date of 1…

Scala中的嵌套循环

Scala中的嵌套循环 (Nested loop in Scala) In programming, a nested loop is used in initializing or iterate multi-dimensional array or to print patterns. Scala provides an efficient method to use nested loops in the programming language. The most used nested…

python基础-字典

字典 # 字典是python基本数据结构之一,相对于列表和元组,他是无序的,每次输出都打乱了顺序,没有下标hello{110:{"name":"alex","age":28,"home":"shandong"},111:{"name&…

sql算术运算符_SQL中的算术运算符

sql算术运算符SQL | 算术运算符 (SQL | Arithmetic Operators) Different number-crunching administrators are utilized in SQL to be specific Addition (), Subtraction (-), Multiplication (*), Division (/), Modulus (%). SQL中使用了不同的数字运算管理员来表示特定的…

HDU 6188 Duizi and Shunzi

栈。 将数字排序后&#xff0c;一个一个压入栈。如果栈顶两个元素形成了对子&#xff0c;那么$ans1$&#xff0c;弹出栈顶两个元素&#xff1b;如果栈顶三个元素形成了顺子&#xff0c;那么$ans1$&#xff0c;弹出栈顶三个元素。 #include<bits/stdc.h> using namespace …

php 单例模式有什么缺点_PHP的完整形式是什么?

php 单例模式有什么缺点PHP&#xff1a;超文本预处理器 (PHP: Hypertext Preprocessor ) PHP is an abbreviation of Hypertext Preprocessor, earlier called Personal Home Page. PHP is extensively used HTML-embedded, open-source server-side scripting language create…

Myeclipse有关的问题

Myeclipse配置问题 1.行数显示 window ----preference----General-----Editors-----TextEditors----show line numbers 2.编码设置 window ---preference----workspace-----设置 3.jsp编码设置 window ---preference----myeclipse------Files And Editors------jsp 4.jsp的视图…

weak-to-strong-generalization始终比母体更智能的人工智能,能否被它的母体所监管supervision,从而变的更强

正如supervison这个词&#xff0c;就像就是母亲对孩子的超级super愿景vision&#xff0c;比母亲更聪明更强&#xff0c;也就意味着要按照母亲期望的那样成长&#xff0c;不合理的行为要能够纠正supervison。 一代比一代强&#xff0c;一代比一代好。 弱模型监督能否激发出更强…

最小跳数

Description: 描述&#xff1a; This problem is a standard interview problem which has been featured in interview rounds of Adobe, Amazon, Oyo rooms etc. 此问题是标准的采访问题&#xff0c;已在Adobe&#xff0c;Amazon&#xff0c;Oyo房间等的采访回合中出现。 P…

《Web安全之机器学习入门》一 第3章 机器学习概述

第3章 机器学习概述机器学习的概念非常多&#xff0c;从有监督到无监督&#xff0c;从聚类到回归&#xff0c;从浅层学习到深度学习&#xff0c;从准确率到召回率&#xff0c;它们究竟是什么意思呢&#xff1f;本章将介绍最主要的几个概念。不少机器学习初学者甚至包括业内老司…