Java多线程17:中断机制
概述
之前讲解Thread类中方法的时候,interrupt()、interrupted()、isInterrupted()三个方法没有讲得很清楚,只是提了一下。现在把这三个方法同一放到这里来讲,因为这三个方法都涉及到多线程的一个知识点----中断机制。
Java没有提供一种安全、直接的方法来停止某个线程,而是提供了中断机制。中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理。有个例子举个蛮好,就像父母叮嘱出门在外的子女要注意身体一样,父母说了,但是子女是否注意身体、如何注意身体,还是要看自己。
中断机制也是一样的,每个线程对象里都有一个标识位表示是否有中断请求(当然JDK的源码是看不到这个标识位的,是虚拟机线程实现层面的),代表着是否有中断请求。
三个中断方法
上面说了,中断标识位是JDK源码看不到的,是虚拟机线程实现层面的。下面结合代码逐一看一下这三个方法的作用,以及为什么中断标识位是虚拟机实现层面的:
1、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();
return;
}
}
interrupt0();
}
/* Some private helper methods */
private native void setPriority0(int newPriority);
private native void stop0(Object o);
private native void suspend0();
private native void resume0();
private native void interrupt0();
分两部分看:
(1)第一部分的第8行注释说得很清楚了,interrupt0()方法的作用是"Just to set the interrupt flag",即方法的作用仅仅是设置中断标识位
(2)第二部分的第6行就是interrupt0()方法的原型,由于方法是被native修饰的,很明显这是一个本地方法,是Java虚拟机实现的
2、isInterrupted()
方法唯一的作用只是测试线程是否已经中断,中断标识位的状态并不受到该方法的影响,看一下Java是如何实现这个方法的:
/**
* Tests whether this thread has been interrupted. The <i>interrupted
* status</i> of the thread is unaffected by this method.
*
* <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 this thread has been interrupted;
* <code>false</code> otherwise.
* @see #interrupted()
* @revised 6.0
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
注意一下第一部分的第2行和第3行,"The interrupted statis of the thread is unaffected by this method",即线程的中断状态不受到这个方法的影响。最终调用的是isInterrupted(boolean ClearInterrupted),这个方法是一个native的,看得出也是Java虚拟机实现的。方法的参数ClearInterrupted,顾名思义,清除中断标识位,这里传递false,明显就是不清除
3、interrupted()
方法的作用是测试当前线程是否已经中断,线程的中断标识位由该方法清除。换句话说,连续两次调用该方法的返回值必定是false。看一下这个方法是如何实现的:
/**
* 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);
private native boolean isInterrupted(boolean ClearInterrupted);
同样,第2行和第3行的注释已经写得很清楚了,"The interrupted status of the thread is cleared by this method",即线程的中断状态由此方法清除。另外,interrupted()方法和isInterrupted()方法调用的是同一个native方法,无非这个方法传入的是true,表示清除中断标识位
此外,JDK API中有些类的方法也可能会调用中断,比如FutureTask的cancel,如果传入true则会在正在运行的异步任务上调用interrupt()方法,又如ThreadPoolExecutor中的shutdownNow方法会遍历线程池中的工作线程并调用线程的interrupt()方法。这些场景下只要代码没有对中断作出响应,那么任务将一直执行下去。
中断处理时机
这其实是一个很宽泛的、没有标注答案的话题。显然,作为一种协作机制,不会强求被中断的线程一定要在某个点进行中断处理。实际上,被中断线程只需要在合适的时候处理即可,如果没有合适的时间点,甚至可以不处理。"合适的时间点"就和业务逻辑密切相关了。
处理时机决定着程序的效率和响应的灵敏度。频繁的检查中断可能会导致程序执行效率低下,较少的检查则可能导致中断请求得不到及时响应。在实际场景中,如果性能指标比较关键,可能需要建立一个测试模型来分析最佳的中断检测点,以平衡性能和响应灵敏性。
线程中断举例
写了这么多理论,写一个例子来演示一下中断:
public static void main(String[] args) throws Exception
{
Runnable runnable = new Runnable()
{
public void run()
{
while (true)
{
if (Thread.currentThread().isInterrupted())
{
System.out.println("线程被中断了");
return ;
}
else
{
System.out.println("线程没有被中断");
}
}
}
};
Thread t = new Thread(runnable);
t.start();
Thread.sleep(3000);
t.interrupt();
System.out.println("线程中断了,程序到这里了");
}
看一下运行结果:
...
线程没有被中断
线程没有被中断
线程没有被中断
线程没有被中断
线程没有被中断
线程中断了,程序到这里了
线程被中断了
代码分为以下几步:
1、main函数起一个t线程
2、main函数3秒钟之后给t线程打一个中断标识位,表示t线程要中断
3、t线程无限轮询自己的中断标识位,中断了则打印、退出,否则一直运行
从控制台上打印的语句看到,3秒钟中断后,打印出该打印的语句后,就停止了。那这种场景就是前面说的"频繁地检查",导致程序效率低下;那如果不频繁地检查呢,比如在while中的else分支中加上Thread.sleep(500),表示500ms即0.5s检查一次,那这种场景就是前面说的"中断得不到及时的响应"。
其实这个例子中,t线程完全可以不用去管这个中断标识位的,不去检查就好了,只管做自己的事情,这说明中断标识位设不设置是别人的事情,处不处理是我自己的事情,没有强制要求必须处理中断。
但是,那些会抛出InterruptedException的方法要除外。像sleep、wait、notify、join,这些方法遇到中断必须有对应的措施,可以直接在catch块中处理,也可以抛给上一层。这些方法之所以会抛出InterruptedException就是由于Java虚拟机在实现这些方法的时候,本身就有某种机制在判断中断标识位,如果中断了,就抛出一个InterruptedException。
Java多线程17:中断机制的更多相关文章
- JAVA多线程17个问题
1.Thread 类中的start() 和 run() 方法有什么区别? Thread.start()方法(native)启动线程,使之进入就绪状态,当cpu分配时间该线程时,由JVM调度执行run( ...
- JAVA多线程之中断机制(stop()、interrupted()、isInterrupted())
一,介绍 本文记录JAVA多线程中的中断机制的一些知识点.主要是stop方法.interrupted()与isInterrupted()方法的区别,并从源代码的实现上进行简单分析. JAVA中有3种方 ...
- JAVA多线程之中断机制(如何处理中断?)
一,介绍 这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理.感觉对InterruptedException异常进行处理是一件谨慎且 ...
- java多线程17:ThreadLocal源码剖析
ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...
- Java多线程——中断机制
前言:在Java多线程中,中断一直围绕着我们,当我们阅读各种关于Java多线程的资料.书籍时,“中断”一词总是会出现,笔者对其的理解也是朦朦胧胧,因此非常有必要搞清楚Java多线程的中断机制. 1.J ...
- Java多线程9:中断机制
一.概述 之前讲解Thread类中方法的时候,interrupt().interrupted().isInterrupted()三个方法没有讲得很清楚,只是提了一下.现在把这三个方法同一放到这里来讲, ...
- 50个Java多线程面试题
不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者 ...
- 50个Java多线程面试题(上)
Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者精通多线程技术并且有丰富的 Java 程序开发.调试.优化经验 ...
- Java多线程与并发面试题
1,什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速.比如,如果一个线程完成一 ...
随机推荐
- Oracle数据库导入导出命令总结 (详询请加qq:2085920154)
分类: Linux Oracle数据导入导出imp/exp就相当于oracle数据还原与备份.exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命令可以把dmp文件从本地导入到远处的 ...
- 阻塞非阻塞,同步异步四种I/O方式
举一个去书店买书的例子吧: (同步)阻塞: 你去书店买书,到柜台告诉店员,需要买一本APUE,然后一直在柜台等.(阻塞) 店员拿到书以后交给你. (同步)非阻塞: 你去书店买书,到柜台告诉店员A,需要 ...
- c#一个泛型控制Textbox 和label 控件 泛型方法。
class ControlHelper { public static void ShowOnTxtLbl<T>(T control, string mess) where T : Sys ...
- 炫酷CSS
<!DOCTYPE html><!--To change this license header, choose License Headers in Project Propert ...
- OpenVPN 通过服务器上网
在Windows环境中架设OpenVPN服务相对比较简单,网上这方面的教程也比较丰富,照葫芦画瓢即可.但是大部分教程都只讲了如何将client与Server通过VPN管道连接起来,使client可以正 ...
- mysql解压缩安装(一)
MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果是msi格式的可以直接点击安装,按照它给出的安装提示进行安装(相信大家的英文可以看懂英文提示),一般MySQL将会安装在C:\P ...
- 误打误撞写了段能让电脑奔溃的JS代码,但是自己不知道为什么,高手看到可以解答下吗?
代码如下: <script> for(i=1;j=3*i;i++){ for(;j<=50;){ document.write(j+"<br>") } ...
- 关于.NET大数据量大并发量的数据连接池管理
转自:http://www.cnblogs.com/virusswb/archive/2010/01/08/1642055.html 我以前对.NET连接池的认识是错误的,原来以为在web.confi ...
- GPT分区磁盘上优盘安装win10的方法
刚买的acer笔记本安装的是win8,之后硬盘安装升级到win10.今天想格式化安装win10这样自带的软件可以去除,但是nt6 hdd在win10上无法使用,本来想先安装win7再通过nt6 hdd ...
- IntegerCache类
先看代码实例现象: 问题:为什么都是比较数值,第一个为true,第二个确为false呢? 查找源码(java.lang.Integer),看到如下代码: /** * Cache to support ...