前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jdk1.8之线程中断

jdk1.8之线程中断

作者头像
intsmaze-刘洋
发布2019-01-28 11:29:48
5170
发布2019-01-28 11:29:48
举报

在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 " 线程中断不会使线程立即退出,而是给线程发送一个通知,告知目标线程有人希望你退出。至于目标线程接收到通知后如何处理,则完全由目标线程自行决定。

线程中断有关的三个方法

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

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

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

代码语言:javascript
复制
    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在中断后退出,必须为他增加相应的中断处理代码,如下

代码语言:javascript
复制
    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();我们可以发现,程序一直运行,线程没有停止;反之放开该注释,则发现程序运行结束了。

代码语言:javascript
复制
    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()只会设置线程的中断标志,而不会真正”中断”它,我们看段代码。

代码语言:javascript
复制
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(),线程会一直运行。

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-01-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 线程中断有关的三个方法
    • 等待中的线程(wait(long),sleep(long),join(long)收到中断信号会抛出InterruptedException
      • BLOCKED
        • NEW/TERMINATE
          • IO操作
            • 拿两年前的笔记出来冒个泡
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档