Thread interrupt() 线程中断的详细说明
原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94
一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。Java Thread.interrupt()方法所提供的线程中断,实际就是从线程外界,修改线程内部的一个标志变量,或者让线程中的一些阻塞方法,抛出InterruptedException。以此”通知“线程去做一些事情, 至于做什么,做不做,实际完全是由线程内的业务代码自己决定的。不过一般都是释放资源并结束线程。
基本概念
public static void basic() {
Thread testThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println();
}
});
testThread.interrupt(); //是给线程设置中断标志; 其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程)
testThread.isInterrupted(); //只检测中断; 作用于此线程,即代码中调用此方法的实例所代表的线程;作用是只测试此线程是否被中断 ,不清除中断状态。
testThread.interrupted(); //是检测中断并清除中断状态; 作用于当前线程(作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false)
Thread.interrupted(); //同上
//************************************
testThread.interrupt(); //设置指定testThread线程的状态为中断标志,
testThread.isInterrupted();// 检测当前testThread线程是否被外界中断;是则返回true
testThread.interrupted();//检测当前testThread线程是否收到中断信令,收到信令则返回true且清除中断状态,重新变更为false;
Thread.interrupted();//静态方法,与testThread.interrupted()一样,(检测当前testThread线程是否被中断,如果被中断则返回true且清除中断状态,重新变更为未中断状态;) 作用于当前被执行线程,由于testThread内部线程在执行的时候,是无法获取testThread引用的,所以如果想检测当前自己的线程是否被中断且清除中断状态,则可以使用Thread.interrupted()方法;
//如上,其实关于线程中断一共也就上述三个方法,其中interrupt()和isInterrupted() 是线程实例方法,interrupted()则是线程的静态方法;
//isInterrupted()是线程实例方法,所以,线程内部执行代码中是无法获取testThread的引用的所以无法执行实例方法isInterrupted();
//但其实,我们可以通过在线程内部执行代码中使用 Thread.currentThread()获取当前线程的实例,此时使用Thread.currentThread().isInterrupted() 的方式来调用isInterrupted()方法;等价于testThread.isInterrupted();
//等价与:线程外部做检测用:testThread.isInterrupted(); 线程内部做检测用:Thread.currentThread().isInterrupted()
}
线程中断验证
/**
* 验证一般情况下使用interrupt() 中断执行线程的例子
*/
public static void threadStopTest() {
Thread testThread = new Thread(new Runnable() {
@Override
public void run() {
//第一种情况:检测线程是否收到中断信令,收到则返回true,并清除当前的线程状态,重新变更为未中断;
/* while (!Thread.interrupted()) {
System.out.println("线程内代码执行");
}
//此时再检测当前该线程是否收到外界中断信令,得到结果为false,因为使用Thread.interrupted(),在收到中断信令后,会清除当前的线程状态,所以此处进行判断时则返回结果为false,线程状态未收到中断信令
System.out.println(Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread().isInterrupted());
*/
//第二种情况:检测线程是否收到中断信令,收到则返回true,只是检测当前是否收到中断信令,不清除当前的线程状态,
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程内代码执行");
}
//此时检测当前该线程是否收到外界中断信令,true表示收到,此处获取结果为 true
System.out.println(Thread.currentThread().isInterrupted()); //true
System.out.println(Thread.currentThread().isInterrupted()); //true
//线程被中断后执行该代码块,进行回收工作
System.out.println("线程收到外部中断通知,已进行线程内部回收,中断完成");
/*while (true) {
}*/
}
});
testThread.start();
try {
Thread.sleep(5000);
//等待5秒后 发出中断信号,通知testThread线程进行中断
testThread.interrupt();
//判断当前该线程是否中断完成
boolean flag = true;
int index = 0;
Thread.sleep(1000);
while (flag) {
//获取指定线程是否收到中断信号,返回true表示线程已经收到中断信号,但线程正在运行,处理中;或者是已经收到了中断信令,但是选择了不中断继续执行;
// 如果返回false则存在两种情况
//1、是当前该线程已经执行完毕,完成中断;由于此时线程已经执行完成了,那么此处再获取该线程的信令时则返回为false,
//2、该线程没有完成中断,但是该线程代码内部使用了Thread.interrupted() 清除了线程的信令状态,此时则也是返回结果为false,
System.out.println("检测线程的中断信号:" + testThread.isInterrupted());
//循环检测10秒钟,10秒后则跳出循环
Thread.sleep(1000);
index++;
if (index == 10) {
//停止检测
flag = false;
}
}
if (!testThread.isInterrupted()) {
//TODO: testThread线程中断完成,则执行该代码块
System.out.println("外部检测testThread中断完成");
} else {
//TODO: 否则,则执行另外代码块
System.out.println("外部检测testThread中断失败");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94
验证线程中断,抛出InterruptedException异常的情况
/**
* 验证线程中断,抛出InterruptedException异常的情况;
*/
public static void threadStopTest2() {
/**
* 当外部调用对应线程进行中断的信令时,如果此时该执行线程处于被阻塞状态,如;Thread.sleep(),Object.wait(),BlockingQueue#put、BlockingQueue#take 等
* 那么此时通过调用当前线程对象的interrupt方法触发这些函数抛出InterruptedException异常。
* 当一个函数抛出InterruptedException异常时,表示这个方法阻塞的时间太久了,外部应用不想等它执行结束了。
* 当你的捕获到一个InterruptedException异常后,亦可以处理它,或者向上抛出。
*
* 抛出时要注意???:当你捕获到InterruptedException异常后,当前线程的中断状态已经被修改为false;
* 此时你若能够处理中断,正常结束线程,则不用理会该值;但如果你继续向上抛InterruptedException异常,你需要再次调用interrupt方法,将当前线程的中断状态设为true。
*
*/
Thread testThread = new Thread(new Runnable() {
@Override
public void run() {
try {
//外部调用信令,要中断该线程时,如果此时线程正在休眠或者阻塞中,则将会抛出异常
Thread.sleep(6000);
} catch (InterruptedException e) {
//第一种情况:进入异常捕获,此处捕获到异常,则说明当前该线程被外界要求进行中断,此时我们可以选择中断该线程;那么此时后续的while循环则将不会被执行,线程执行完毕,则结束;
/*if (1 > 0) {
return;
}
*/
//第二种情况:当然,我们也可以选择收到中断信令后,不进行线程中断;比如,当前的线程的确处于正常的阻塞期间,阻塞完成后,我还是要执行while循环的,等到最终while循环执行完毕后,才正常的结束线程的生命周期;
//那么此时,捕获到异常后不做任何操作即可;需要注意的是,此时捕获了InterruptedException异常后,此时的线程状态将会自动被修改为false
// (false表示线程没有收到过中断信令,或者是线程已经中断完成,或者是线程使用了Thread.interrupted()清除了信令状态)没有收到过中断信令这个基本是不可能的,只要外部有进行调用,则百分百收到信令,除非是在调用中断信令前,获取了一下线程的状态,此时则肯定是false的;如:先执行,testThread.isInterrupted(),再执行testThread.interrupt();则此时第一个执行的isInterrupted()肯定是false,这个场景意义不大;
//1、对于外界来说,收到线程的信令状态是false,则表示该线程已经是执行完成了;当然存在线程信令为false是内部线程自己进行了转换,但实际上并没有停止线程执行的情况;
//所以一般情况下,按照约定来说,如果内部线程收到中断请求后,此时如果需要继续执行,不理会外部的中断信令,那么此时可以执行:Thread.currentThread().interrupt();重新将内部状态转换为true
//这样,外部线程在重新检测当前线程的信令状态时为true时,则知道,内部线程已经收到了中断信令,而不是一直没有收到中断信令。
//此处为false,捕获该中断异常后,将会自动修改线程状态为false,
System.out.println("异常" + Thread.currentThread().isInterrupted());
//此处由于要继续执行该线程,不执行线程中断,所以重新修改中断状态为true;
Thread.currentThread().interrupt();
//此时获取结果为true;
System.out.println("异常" + Thread.currentThread().isInterrupted());
}
while (true) {
System.out.println("线程内部执行中");
}
}
});
testThread.start();
//发出线程中断信令
testThread.interrupt();
}
约定
/**
* 约定:
* 内部中断的线程,如果需要继续执行,则必须重新设置信令状态为true;此时外部调用者才会清楚当前线程已经收到中断信令但是还要继续执行;
* <p>
* 什么情况下,线程状态会自动变更为false?
* <p>
* 1、线程自动执行完毕后,则状态将会自动置为 false;
* 2、线程内部使用:Thread.interrupted()方法获取线程状态时,将会自动清除线程状态,使当前线程状态重新更改为false;
* 3、线程内部如果捕获了,InterruptedException异常,那么此时线程状态也会自动修改为false;
* <p>
* 所以,
* 1、如果是使用Thread.interrupted()来获取线程状态的情况,使用完以后,必须保证线程是正常中断的;如果不能保证,建议使用Thread.currentThread().isInterrupted()来获取线程状态;isInterrupted()方法只获取线程状态,不会更改线程状态;
* 2、对于线程内使用try catch 捕获了InterruptedException异常的情况,则捕获完以后,一定要做相关操作,而不要只捕获异常,但是不处理该中断信令;
* 当前捕获到异常后,如果需要中断,则直接中断线程即可
* 当前捕获到异常后,如果不需要中断,需要继续执行线程,则此时需要执行Thread.currentThread().interrupt();重新更改下自己的线程状态为true,表示当前线程需要继续执行;
* 当前捕获到异常后,如果不需要中断,而是将异常外抛给上层方法进行处理,那么此时也需要执行Thread.currentThread().interrupt();重新更改下自己的线程状态为true,表示当前线程需要继续执行;
*/
public static void main(String[] args) throws InterruptedException {
// threadStopTest();
/*
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().isInterrupted());true
System.out.println(Thread.currentThread().isInterrupted());true
System.out.println(Thread.currentThread().isInterrupted());true
System.out.println(Thread.interrupted());true
System.out.println(Thread.currentThread().isInterrupted());false
System.out.println(Thread.interrupted());false
*/
}
原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94
Thread interrupt() 线程中断的详细说明的更多相关文章
- boost::thread编程-线程中断(转)
原文转自 http://blog.csdn.net/anda0109/article/details/41943691 thread的成员函数interrupt()允许正在执行的线程被中断,被中断的线 ...
- 线程中断:Thread类中interrupt()、interrupted()和 isInterrupted()方法详解
首先看看官方说明: interrupt()方法 其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行. i ...
- Synchronized之三:Synchronized与线程中断、线程wait
线程中断 见<Thread之八:interrupt中断> 正如中断二字所表达的意义,在线程运行(run方法)中间打断它,在Java中,提供了以下3个有关线程中断的方法 //中断线程(实例方 ...
- java高并发系列 - 第11天:线程中断的几种方式
java高并发系列第11篇文章. 本文主要探讨一下中断线程的几种方式. 通过一个变量控制线程中断 代码: package com.itsoku.chat05; import java.util.con ...
- Java Thread.interrupt 害人! 中断JAVA线程(zz)
http://www.blogjava.net/jinfeng_wang/archive/2012/04/22/196477.html#376322 ————————————————————————— ...
- 注意Thread.interrupt()方法的真正作用并不是用来中断线程
程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误. 在本篇文章中,我们针对这些难题之一:如何中断一个正在 ...
- java基础知识回顾之java Thread类学习(十二)-- 线程中断
官方文档翻译: 如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), ...
- Thread线程中断相关方法
public class Demo { /* * 线程中断相关方法 * ---------------------------------------------------------------- ...
- 【杂谈】线程中断——Interrupt
前言 以前有一个错误的认识,以为中断操作都会抛出异常,后来才发现并不是这样,所以今天就来做一个关于中断的总结. 如何关闭线程 已被弃用的Stop方法 早期,Thread类中有一个stop方法,用于强行 ...
随机推荐
- 炸了!一口气问了我18个JVM问题!
前言 GC 对于Java 来说重要性不言而喻,不论是平日里对 JVM 的调优还是面试中的无情轰炸. 这篇文章我会以一问一答的方式来展开有关 GC 的内容. 不过在此之前强烈建议先看这篇文章深度揭秘垃圾 ...
- 关于 node build/build.js 卡顿的问题
今天也是奇了怪了,npm run dev 可以正常执行,但node build/build.js 就死活不行,卡住不动 实在不行,就有了"重启"万能大法,结果依然不行.实在无奈, ...
- jquery实现回车键执行ajax
$('#txtKey').bind('keypress',function(event){ if(event.keyCode == "13") { alert(1) }});
- [MIT6.006] 20. Daynamic Programming II: Text Justification, Blackjack 动态规划II:文本对齐,黑杰克
这节课通过讲解动态规划在文本对齐(Text Justification)和黑杰克(Blackjack)上的求解过程,来帮助我们理解动态规划的通用求解的五个步骤: 动态规划求解的五个"简单&q ...
- 利用日志文件getshell
一.包含日志文件漏洞利用概述 当我们没有上传点,并且也没有url_allow_include功能时,我们就可以考虑包含服务器的日志文件. 利用思路也比较简单,当我们访 ...
- nginx&http 第四章 ngx http代理 && 转载
Nginx访问上游服务器的流程大致分以下几个阶段:启动upstream.连接上游服务器.向上游发送请求.接收上游响应(包头/包体).结束请求. upstream相关的两个重要数据结构ngx_http_ ...
- linux nf_conntrack 连接跟踪机制
PRE_ROUTING和LOCAL_OUT点可以看作是整个netfilter的入口,而POST_ROUTING和LOCAL_IN可以看作是其出口; 报文到本地:PRE_ROUTING----LOCAL ...
- 四:Redis五大数据类型
Redis的五大数据类型 1.string(字符串) string是Redis最基本的类型,你可以理解成与menmcached一模一样的类型,一个key对应一个value string类型是二进制安全 ...
- CTDB使用radosobject作为lockfile
前言 服务器的服务做HA有很多种方式,其中有一种就是是用CTDB,之前这个是独立的软件来做HA的,现在已经跟着SAMBA主线里面了,也就是跟着samba发行包一起发行 之前CTDB的模式是需要有一个共 ...
- Linux中Python自动输入sudo 密码
一.背景和需求 背景: 由于docker服务进程都是以root帐号的身份运行的,所以用docker跑abpred出来的文件所有者都是root, 而我作为一般用户,操作这个文件不够权限,运行代码时需要s ...