线程应用 - 中断interrupt详解
有些初学者对中断的概念可能会有些许小误会,比如线程调用Thread.interrupt()方法,就认为线程会被中断,停止执行,其实不是这样的,让我们来看下中断interrupt详解。
一、interrupt方法
源码如下:
public void interrupt() { //判断是否操作线程
if (this != Thread.currentThread())
checkAccess(); synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) { //只是设置中断标记位
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
可以看到interrupt方法并不会对任务终止线程的操作,仅仅只是设置了一个中断的标记位。为了不造成误解,我们看以下示例:
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
}
System.out.println("当前运行数字为:" + i);
}
}
}
如果interrupt方法会直接终止线程的话,那么当上述代码中的i为10时,后面就不会再继续执行下去了,运行结果为:
可以看到线程还是运行到了最后。正如源码中所说的那样,调用interrupt仅仅只是做了一个中断标识而已,其余并不会做任何操作。
但是也不能说interrupt方法是完全没有任何作用的,因为interrupt方法对于java来说其实是一个协作机制,调用interrupt方法会把调用线程的中断状态设置为true,而其他需要依赖这个中断符的方法在运行时如果监测到这个中断标志就会作出响应。
下面示例,使用Thread.sleep方法观察运行结果。
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
System.out.println("线程调用中断方法:" + i);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("当前运行数字为:" + i);
}
}
}
运行结果:
上述运行过程中每一次循环都会调用Thread.sleep方法,将线程休眠1秒钟,然而当第10次循环,调用interrupt方法后再调用休眠方法则抛出了异常。
这样的情况在Object.wait等方法中也会出现。所以interrupt相当于java的一个协作机制,如果调用了Object.wait或Thread.sleep方法,会判断线程的中断标志位,如果发现他被设置为true后(线程可以调用interrupt方法来修改标志位),则会抛出异常,后续如果线程不想继续被操作,可以利用这个异常来让线程运行退出,比如for循环的break,或者直接return。
二、isInterrupted方法
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
检测线程是否中断方法,如果当前线程已经中断则返回true,否则返回false。继续使用上述例子,观察结果:
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
System.out.println("线程调用中断方法:" + i);
boolean flag = this.isInterrupted();
System.out.println("线程是否被中断:" + flag);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("当前运行数字为:" + i);
}
}
}
运行结果:
结果发现,线程是否被中断检测方法返回了true。
三、interrupted方法
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
interrupted方法是线程类中的静态方法,在api文档中的说明为返回并清除中断状态。
使用上述例子并将isInterrupted方法替换为interrupted方法。观察结果:
public class InterruptTest {
public static void main(String[] args) {
new test().start();
}
}
class test extends Thread {
static int n = 10;
public void run() {
for (int i = 0; i < 15; i++) {
if (i == n) {
System.out.println("线程要被中断了:" + i);
this.interrupt();
System.out.println("线程调用中断方法:" + i);
boolean flag = Thread.interrupted();
System.out.println("线程是否被中断:" + flag);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("当前运行数字为:" + i);
}
}
}
运行结果:
上述结果发现,线程在调用Thread.sleep后并没有被中断。加入isInterrupted方法观察线程中断标志位情况:
运行结果说明调用中断方法后调用Thread.sleep方法,没有中断的原因是因为调用了interrupted方法,将中断标志位重置为了false。而interrupted方法返回了true是因为,在重置之前,他的中断标志位是正常的。
四、总结
上述测试和分析了以后对这三个方法应该就比较清晰了。
(1)interrupt方法其实是修改中断标记位为true,起到一个协助的作用,但是并不会真正的终止线程。
(2)isInterrupted方法最纯粹,就是判断当前线程是否有中断标记位,返回结果为true或false。
(3)interrupted方法是一个静态方法,返回的是调用方法前的中断标记位,并清除中断标记位为false。
- Leetcode-Easy 804. Unique Morse Code Words
- JavaScript设计模式与开发实践 - 策略模式
- 二叉树的深度
- [html5] (Notification) 桌面通知
- React第三方组件4(状态管理之Reflux的使用④TodoList下)
- Leetcode-Easy 155. Min Stack
- Leetcode-Easy 72. Edit Distance
- React第三方组件4(状态管理之Reflux的使用③TodoList中)
- Leetcode-Easy21. Merge Two Sorted ListsDefinition for singly-linked list.class ListNode:def init(sel
- Burp Suite详细使用教程-Intruder模块详解
- 逆元的三种解法(附详细证明)
- JavaScript设计模式与开发实践 - 单例模式
- Leetcode-Easy 141. Linked List Cycle
- 【DataMagic】如何在万亿级别规模的数据量上使用Spark
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- WebSphere XXE 漏洞分析(CVE-2020-4643)
- 专项行动的意外收获—— 2020 年 9 月墨子(Mozi)僵尸网络分析报告
- React 17.0.0-rc.2带来全新的JSX转换
- 下载b站外挂字幕,用 potplayer 播放视频也能看字幕了
- MySQL一个字符集转换的骚操作,酿下性能的苦果
- CentOS7下部署Cobbler实现PXE+Kickstart自动化安装【脚本版】
- 腾讯云主机上部署FRP+Teamviewer穿透内网进行远程运维
- 从今天起构建你的JavaScript世界
- SpringCloud开发框架入门知识
- 一张900w的数据表,怎么把原先要花费17s执行的SQL优化到300ms?
- Codeforces Round #624 (Div. 3) A - Add Odd or Subtract Even
- XMLHttpRequest
- Codeforces Round #624 (Div. 3) B - WeirdSort
- 详解 Ajax
- 这个腾讯博客是被腾讯爬虫爬过来的,样式丑,请看我博客园地址,见下文