• jdk1.8之线程中断


    在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(),线程会一直运行。

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

  • 相关阅读:
    [python] pprika:基于werkzeug编写的web框架(6) ——restful的错误处理
    [python] pprika:基于werkzeug编写的web框架(5) ——蓝图blueprint
    [python] pprika:基于werkzeug编写的web框架(4) ——请求上下文与helpers
    [python] pprika:基于werkzeug编写的web框架(3) ——错误处理
    [python] pprika:基于werkzeug编写的web框架(2) ——路由与请求响应
    [python] pprika:基于werkzeug编写的web框架(1) ——序言与简介
    2019寒假训练营第四次作业
    2019寒假训练营第三次作业
    【学习笔记】福州大学网络课程 网络空间安全概论(5)
    【学习笔记】福州大学网络课程 网络空间安全概论(1,4)
  • 原文地址:https://www.cnblogs.com/intsmaze/p/10285850.html
Copyright © 2020-2023  润新知