并发编程补充--方法interrupted、isinterrupted详解
并发编程
interrupted()源码
/**
* Tests whether the current thread has been interrupted. The
* <i>interrupted status</i> of the thread is cleared by this method. In
* other words, if this method were to be called twice in succession, the
* second call would return false (unless the current thread were
* interrupted again, after the first call had cleared its interrupted
* status and before the second call had examined it).
*
* <p>A thread interruption ignored because a thread was not alive
* at the time of the interrupt will be reflected by this method
* returning false.
*
* @return <code>true</code> *if the current thread has been interrupted*;
* <code>false</code> otherwise.
* @see #isInterrupted()
* @revised 6.0
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
重点看下方法上的注释:Tests whether the current thread has been interrupted。The
* interrupted status of the thread is cleared by this method。
从上面两句话中,可得知,此方法返回的是当前线程是否被打断,如果是则为true,并且调用此方法后,interrupted status这种状态会被清除,清除逻辑是通过调用currentThread.isInterrupted()方法,并入参为true实现的
isInterrupted源码
/**
* Tests if some Thread has been interrupted. The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/
private native boolean isInterrupted(boolean ClearInterrupted);
解读:调用isInterrupted方法时,会跟如入参ClearInterrupted决定是否重新设定interrupted state,true则重置,false则不执行,由于为本地方法,不能查看源码,但是根据源码注释是可以推断出来的,不传参会默认为false.
总结:
- interrupted()是静态方法:内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态
- isInterrupted()是实例方法,是调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态
接下来进行代码展示环节



中断线程Interrupted的用处
线程状态
Java虚拟机将线程运行过程分成四种状态 。 (1) New 新生;(2) Runnable 可运行;(3) Blocked 阻塞;(4) Dead 死亡。
值得注意的是: 线程的可运行状态并不代表线程一定在运行(runnable != running ) 。 大家都知道:所有现代桌面和服务器操作系统都使用了抢占式的线程调度策略 。一旦线程开始执行,并不是总是保持持续运行状态的。当系统分给它的时间片(非常小的运行时间单位)用完以后,不管程序有没有执行完,线程被强制放弃CPU,进入就绪状态,直到下次被调度后开始继续执行。也就是说, Runnable可运行状态的线程处于两种可能的情况下:(1)占用CPU运行中,(2)等待调度的就绪状态。 这里要声明一下:处于等待调度的就绪状态线程和处于阻塞的线程是完全不同的。就绪的线程是因为时间片用完而放弃CPU,其随时都有可能再次获得CPU而运行,这一切取决于分时OS的线程调度策略。
在很多操作系统的专业术语中,这种因时间片用完而被剥夺CPU的情况我们叫做线程中断 。注意这和我们下面要将得中断线程是两个完全不同的概念。事实上,我们不可能通过应用程序来控制CPU的线程中断,除非我们能够自由调用OS的内核。
中断线程
一个正在运行的线程除了正常的时间片中断之外,能否被其他线程控制?或者说其他线程能否让指定线程放弃CPU或者提前结束运行? 除了线程同步机制之外,还有两种方法:
(1) Thread.stop(), Thread.suspend(), Thread.resume() 和Runtime.runFinalizersOnExit() 这些终止线程运行的方法 。这些方法已经被废弃,使用它们是极端不安全的。
(2) Thread.interrupt() 方法是很好的选择。但是使用的时候我们必须好好理解一下它的用处。
//无法中断正在运行的线程代码
class TestRunnable implements Runnable{
public void run(){
while(true)
{
System.out.println( "Thread is running..." );
long time = System.currentTimeMillis();//去系统时间的毫秒数
while((System.currentTimeMillis()-time < 1000)) {
//程序循环1秒钟,不同于sleep(1000)会阻塞进程。
}
}
}
}
public class ThreadDemo{
public static void main(String[] args){
Runnable r=new TestRunnable();
Thread th1=new Thread(r);
th1.start();
th1.interrupt();
}
}
//运行结果:一秒钟打印一次Thread is running...。程序没有终止的任何迹象
上面的代码说明interrupt()并没有中断一个正在运行的线程,或者说让一个running中的线程放弃CPU。那么interrupt到底中断什么。
首先我们看看interrupt究竟在干什么。
当我们调用th1.interrput()的时候,线程th1的中断状态(interrupted status) 会被置位。我们可以通过Thread.currentThread().isInterrupted() 来检查这个布尔型的中断状态。
在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "。好好体会这句话的含义,看看下面的代码:
//Interrupted的经典使用代码
public void run(){
try{
....
while(!Thread.currentThread().isInterrupted()&& more work to do){
// do more work;
}
}catch(InterruptedException e){
// thread was interrupted during sleep or wait
}
finally{
// cleanup, if required
}
}
很显然,在上面代码中,while循环有一个决定因素就是需要不停的检查自己的中断状态。当外部线程调用该线程的interrupt 时,使得中断状态置位。这是该线程将终止循环,不在执行循环中的do more work了。
这说明: interrupt中断的是线程的某一部分业务逻辑,前提是线程需要检查自己的中断状态(isInterrupted())。
但是当th1被阻塞的时候,比如被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞时。调用它的interrput()方法。可想而知,没有占用CPU运行的线程是不可能给自己的中断状态置位的。这就会产生一个InterruptedException异常。
//中断一个被阻塞的线程代码
class TestRunnable implements Runnable{
public void run(){
try{
Thread.sleep(1000000); //这个线程将被阻塞1000秒
}catch(InterruptedException e){
e.printStackTrace();
//do more work and return.
}
}
}
public class TestDemo2{
public static void main(String[] args) {
Runnable tr=new TestRunnable();
Thread th1=new Thread(tr);
th1.start(); //开始执行分线程
while(true){
th1.interrupt(); //中断这个分线程
}
}
}
/*运行结果:
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at TestRunnable.run(TestDemo2.java:4)
at java.lang.Thread.run(Unknown Source)*/
并发编程补充--方法interrupted、isinterrupted详解的更多相关文章
- java并发编程(七)synchronized详解
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized( ...
- Java 并发编程(一) → LockSupport 详解
开心一刻 今天突然收到花呗推送的消息,说下个月 9 号需要还款多少钱 我就纳了闷了,我很长时间没用花呗了,怎么会欠花呗钱? 后面我一想,儿子这几天玩了我手机,是不是他偷摸用了我的花呗 于是我找到儿子问 ...
- 并发编程 Semaphore的使用和详解
类Semaphore的基本使用 Semaphore的作用:限制线程并发的数量 课外话题[多线程的同步概念]:其实就是排着队去执行一个任务,执行任务是一个一个的执行,这样的优点是有助于程序逻辑的正确性, ...
- VMware 虚拟化编程(5) — VixDiskLib 虚拟磁盘库详解之一
目录 目录 前文列表 VixDiskLib 虚拟磁盘库 虚拟磁盘数据的传输方式 Transport Methods VixDiskLib_ListTransportModes 枚举支持的传输模式 Vi ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java多线程编程中Future模式的详解<转>
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- Python编程之列表操作实例详解【创建、使用、更新、删除】
Python编程之列表操作实例详解[创建.使用.更新.删除] 这篇文章主要介绍了Python编程之列表操作,结合实例形式分析了Python列表的创建.使用.更新.删除等实现方法与相关操作技巧,需要的朋 ...
- Java程序设计(2021春)——第一章课后题(选择题+编程题)答案与详解
Java程序设计(2021春)--第一章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第一章课后题(选择题+编程题)答案与详解 第一章选择题 1.1 Java与面向对象程 ...
随机推荐
- Spark Streaming和Kafka整合是如何保证数据零丢失
转载:https://www.iteblog.com/archives/1591.html 当我们正确地部署好Spark Streaming,我们就可以使用Spark Streaming提供的零数据丢 ...
- VUE项目性能优化实践——通过懒加载提升页面响应速度
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 最近我司因业务需求,需要在一个内部数据分析平台集成在线Excel功能,既然我 ...
- 如果你的 HTML 里全是 div,那就要小心了
做前端开发的同学都知道,一个网页的基本组成部分是 HTML,JavaScript 和 CSS.开发人员通常更关注 JavaScript 和 CSS ,实践着各种语言规范和设计模式.对于 HTML 的关 ...
- WPF 关于拖拽打开文件的注意事项
由于开发需求,需要开发一个类似Win图片浏览的工具 当然也涉及到了拖拽打开的需求 按照固有思路: <Grid x:Name="grid1" AllowDrop="T ...
- 在mapper.xml映射文件中添加中文注释报错
问题描述: 在写mapper.xml文件时,想给操作数据库语句添加一些中文注释,添加后运行报如下错误: 思考 可能是写了中文注释,编译器在解析xml文件时,未能成功转码,从而导致乱码.但是文件开头也采 ...
- HP Proliant DL580 gen9 阵列卡P440AR 高速缓存 被禁用
摘录内容: IMPORTANT: This issue does NOT occur when the operating system shuts down gracefully. In addit ...
- MongoDB的管理-深度长文
(1) 启动和停止MongoDB: Ubuntu18下启动关闭MongoDB 启动MongoDB: 方法一: systemctl start mongod.service 方法二: 在MongoDB的 ...
- 十六:SQL注入之查询方式及报错盲注
在很多注入时,有很多注入会出现无回显的情况,其中不回显的原因可能是SQL查询语句有问题,这时候我们需要用到相关的报错或者盲注进行后续操作,同时作为手工注入的时候,需要提前了解SQL语句能更好的选择对应 ...
- 【MySQL】DDL数据定义语言的基本用法create、drop和alter(增删改)
DDL 的基础语法 文章目录 DDL 的基础语法 对数据库进行定义 对数据表进行定义 创建表结构(数据表) 设计工具 修改表结构 小结 参考资料 简单复习一波 SQL必知必会 DDL 的英文全称是 D ...
- 代码审计 - BugkuCTF
extract变量覆盖: 相关函数: extract()函数:从数组中将变量导入到当前的符号表.把数组键名作为变量名,数组的键值作为变量值.但是当变量中有同名的元素时会默认覆盖掉之前的变量值. tri ...