在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "

线程中断不会使线程立即退出,而是给线程发送一个通知,告知目标线程有人希望你退出。至于目标线程接收到通知后如何处理,则完全由目标线程自行决定。

线程中断有关的三个方法

  • void Thread.interrupt();//中断线程
  • boolean Thread.isInterrupted()//判断是否中断
  • static boolean Thread.interrupted()//判断是否中断,并清除当前中断状态
  • Thread.interrupt()方法是一个实例方法,它通知目标线程中断,也就是设置中断标志位。中断标志位表示当前线程已经被中断了。
  • Thread.isInterrupted()方法也是实例方法,它判断当前线程是否有被中断(通过检查中断标志位)。

静态方法Thread.interrupted()也是用来判断当前线程的中断状态,但同时会清除当前线程的中断标志位状态。

运行中的线程不会因为interrupt()而中断,因为它仅仅是一个信号(status)

    public static void main(String[] intsmaze) throws InterruptedException {
Thread t1=new Thread()
{
public void run()
{
while(true){ }
}
};
t1.start();
Thread.sleep(2000);
t1.interrupt();
}

这个程序虽然对t1进程了中断,但是在t1中并没有中断处理的逻辑,因此即使t1线程被置上了中断状态,但是这个中断不会发生任何作用。

如果希望t1在中断后退出,必须为他增加相应的中断处理代码,如下

    public static void main(String[] intsmaze) throws InterruptedException {
Thread t1=new Thread()
{
public void run()
{
while(true)
{
if(Thread.currentThread().isInterrupted())//判断当前线程是否中断。
{
System.out.println("intsmaze Interrupt");
break;
}
}
}
};
t1.start();
Thread.sleep(2000);
t1.interrupt();
}

等待中的线程(wait(long),sleep(long),join(long)收到中断信号会抛出InterruptedException

public static native void sleep(long millis) throws InterruptedException;会抛出一个中断异常。当线程在休眠sleep时,如果被中断就会产生该异常,此时它会清楚中断标志,如果不加处理,那么在下一次循环开始时,就无法捕获这个中断。

如果注释掉catch中的Thread.currentThread().interrupt();我们可以发现,程序一直运行,线程没有停止;反之放开该注释,则发现程序运行结束了。

    public static void main(String[] intsmaze) throws InterruptedException {
Thread t1=new Thread()
{
public void run()
{
while(true)
{
if(Thread.currentThread().isInterrupted())
{
System.out.println("intsmaze Interrupt");
break;
}
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
System.out.println("Interrupt when intsmaze sleep");
Thread.currentThread().interrupt();//设置中断状态
}
}
}
}; t1.start();
Thread.sleep(2000);
t1.interrupt();
}

BLOCKED

如果线程在等待锁,对线程对象调用interrupt()只是会设置线程的中断标志位,线程依然会处于BLOCKED状态,也就是说,interrupt()并不能使一个在等待锁的线程真正”中断”。通过前面的代码可以看到,中断是通过循环不判进行Thread.currentThread().isInterrupted()判断的。

在使用synchronized关键字获取锁的过程中不响应中断请求,这是synchronized的局限性。如果想在等待获取锁的过程中能响应中断,应该使用显式锁,Lock接口,它支持以响应中断的方式获取锁。

NEW/TERMINATE

如果线程尚未启动(NEW),或者已经结束(TERMINATED),则调用interrupt()对它没有任何效果,中断标志位也不会被设置。比如说,以下代码的输出都是false。

IO操作

如果线程在等待IO操作,尤其是网络IO,则会有一些特殊的处理。

如果IO通道是可中断的,即实现了InterruptibleChannel接口,则线程的中断标志位会被设置,同时,线程会收到异常ClosedByInterruptException。

如果线程阻塞于Selector调用,则线程的中断标志位会被设置,同时,阻塞的调用会立即返回。

我们重点介绍另一种情况,InputStream的read调用,该操作是不可中断的,如果流中没有数据,read会阻塞 (但线程状态依然是RUNNABLE),且不响应interrupt(),与synchronized类似,调用interrupt()只会设置线程的中断标志,而不会真正”中断”它,我们看段代码。

public class InterruptReadDemo {
private static class A extends Thread {
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
try {
System.out.println(System.in.read());
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("exit");
}
}
public static void main(String[] args) throws InterruptedException {
A t = new A();
t.start();
Thread.sleep(100);
t.interrupt();
}
}

线程t启动后调用System.in.read()从标准输入读入一个字符,不要输入任何字符,我们会看到,调用interrupt()不会中断read(),线程会一直运行。

拿两年前的笔记出来冒个泡

jdk1.8之线程中断的更多相关文章

  1. GDB 多线程调试:只停止断点的线程,其他线程任然执行; 或只运行某些线程 其他线程中断

    多线程调试之痛 调试器(如VS2008和老版GDB)往往只支持all-stop模式,调试多线程程序时,如果某个线程断在一个断点上,你的调试器会让整个程序freeze,直到你continue这个线程,程 ...

  2. java并发编程(二)线程中断

    参考:http://blog.csdn.net/ns_code/article/details/17091267 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thre ...

  3. java 线程的终止与线程中断

    关于线程终止: 1.一般来讲线程在执行完毕后就会进入死亡状态,那该线程自然就终止了. 2.一些服务端的程序,可能在业务上需要,常驻系统.它本身是一个无穷的循环,用于提供服务.那对于这种线程我们该如何结 ...

  4. java线程中断和终止线程运行

    ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...

  5. Java线程中断的本质深入理解(转)

    一.Java中断的现象 首先,看看Thread类里的几个方法: public static boolean interrupted 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如 ...

  6. Java并发编程(2):线程中断(含代码)

    使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回.这 ...

  7. 转:【Java并发编程】之二:线程中断(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17091267 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应 ...

  8. Java并发之线程中断

    前面的几篇文章主要介绍了线程的一些最基本的概念,包括线程的间的冲突及其解决办法,以及线程间的协作机制.本篇主要来学习下Java中对线程中断机制的实现.在我们的程序中经常会有一些不达到目的不会退出的线程 ...

  9. 《Java并发编程》之线程中断与终止线程运行

    Java中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线 ...

随机推荐

  1. ES搜索引擎集群模式搭建【Kibana可视化】

    一.简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎(与Solr类似),基于RESTful web接口.Elasticsearch是用Ja ...

  2. js实现进度条

    不多说,直接上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  3. oracle数据库访问形式

    1. sql plus访问, sqlplus.exe 2. sql developer访问,sqldeveloper.exe 3. pl/sql 自己下载 4. browse https://loca ...

  4. CISCO 过载NAT配置(小型网络)

    一.实验涉及技术  vlan(虚拟局域网). svi(三层交换) .nat(网络地址转换).static router(静态路由) 三.实验目的: 通过配置过载NAT从而实现企业内网正常访问公网,PC ...

  5. 分布式UUID的生成

    背景 最近有个项目:涉及到分布式计算,tps相对较高,流程之间是异步调用,流程间相互依赖的对象(涉及记录外键)需要持久化.这就衍生出了需要在JVM中快速生成分布式UUID的问题 方案 1.通过JDK标 ...

  6. 微服务---Eureka注册中心(服务治理)

    在上一篇的初识SpringCloud微服务中,我们简单讲解到服务的提供者与消费者,当服务多了之后,会存在依赖与管理之间混乱的问题,以及需要对外暴露自己的地址,为了解决此等问题,我们学习Eureka注册 ...

  7. 【HNOI2016】树

    [HNOI2016]树 题目描述 每一个复制过来的子树(我们称为一个树团)有用的只有需要被访问的节点,包括根,根的父亲,要询问的点.我们只需要求出这些点到其所在树团根的距离以及倍增数组就好了. 需要讨 ...

  8. C#事件の事件解析

    事件(event)是基于windows消息处理机制的类,封装的更好,让开发者无须知道底层的消息处理机制,就可以开发出强大的基于事件的应用程序来.委托(delegate)委托可以理解成为函数指针,不同的 ...

  9. windows通过node环境搭建安装npm,cnpm,vue-cli

    1首先下载node,官网地址:https://nodejs.org/en/ 左边是稳定版,右边是最新版,安装过程一样,我选择的是稳定版. 按照步骤一步一步的安装就行,注意路径就可以了. 友情链接:ht ...

  10. nginx配置tomcat负载均衡,nginx.conf配置文件的配置