老猫喜欢今日爬山

老猫喜欢今日爬山

一、概念

1.1 interrupt方法应用场景

  • 用来打断正在阻塞的线程:sleep/wait/join
  • 打断正常的线程

1.2 interrupt() 方法

        Thread类的实例方法,其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。)作用与正常线程会将中断标记设置为true,但是作用于阻塞线程会将中断标志刷新false(中断标记默认为false,刷新就是重新刷会默认)。

1.3 interrupted() 方法

        Thread类的静态方法,作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。

1.4 isInterrupted() 方法

        Thread类的实例方法,作用是只测试此线程是否被中断,不清除中断状态。

二、实例

2.1 打断正常线程,不停止线程

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (true){
                //让thread线程不断运行
            }
        });
        t.start();
        Thread.sleep(1000);//让主线程睡一会
        t.interrupt();//打断正在正常运行的thread
        System.out.println(t.isInterrupted());
    }
}

程序不会停止

Java多线程interrupt、interrupted、isInterrupted详解-LMLPHP

2.2 打断正常线程,并停止线程

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while (Thread.currentThread().isInterrupted()){
                break;
            }
        });
        t.start();
        Thread.sleep(1000);//让主线程睡一会
        t.interrupt();//打断正在正常运行的thread
        System.out.println(t.isInterrupted());
    }
}

程序停止

2.3 阻塞线程打断

作用于阻塞线程会将中断标志刷新false

public static void main(String[] args) throws InterruptedException {
        Thread thread1=new Thread(()-> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        );
        thread1.start();
        thread1.interrupt();
        System.out.println(thread1.isInterrupted());
    }

输出:

Java多线程interrupt、interrupted、isInterrupted详解-LMLPHP
        这里我们发现输出的是true!这里不是我们前面的结论,打断阻塞的线程不是刷新打断状态为false吗?这里牵扯到并发于并行的概念,这里从主线程运行,而thread1是主线程下的线程,这里先执行的是interrupt()方法,然后才执行的是sleep方法,所以打断的时候它是正常的线程,打断状态为true。

        如果我们换成下面这些代码则会让thread1先睡眠,后打断,这样就会在睡眠阻塞中被打断那么就会刷新,这样打断位就为false!!

    public static void main(String[] args) throws InterruptedException {
        Thread thread1=new Thread(()-> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        );
        thread1.start();
      Thread.sleep(1000);
        thread1.interrupt();
        System.out.println(thread1.isInterrupted());
    }

Java多线程interrupt、interrupted、isInterrupted详解-LMLPHP

        这里我们就是false,因为这里在thread1.interrupt();前让主线程睡一会,让thread1有时间进入到睡眠的状态,这样才会造成我们想要的在睡眠阻塞中打断。

三、两阶段终止设计模式

        这里涉及到在线程T1里如何就“优雅”的终止线程T2(例如上面在主线程中如何优雅终止线程thread)
        优雅:指的不是直接杀死T2,而是给T2一个料理后事的机会。直接杀死不好,stop方法现在也被废弃,就是不让大家直接杀死线程。

Java多线程interrupt、interrupted、isInterrupted详解-LMLPHP

public class Demotest {

    public static void main(String[] args) throws InterruptedException {
        ThreadMonitor threadMonitor=new ThreadMonitor();
        threadMonitor.start();
        Thread.sleep(3000);//让主线程睡一会
        threadMonitor.stop();

    }

}
class ThreadMonitor{
    private Thread mnoitor;

    //启动被监控的线程
    public void start(){
        mnoitor=new Thread(()->{
            while (true){
                Thread nowthread=Thread.currentThread();//获取当前线程
                if (nowthread.isInterrupted()){//有被打断则调用stop方法
                    break;
                }
                try {
                    nowthread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    nowthread.interrupt();//设置打断标志为true
                    System.out.println("设置了打断标记");
                }
            }
        });
        mnoitor.start();
    }

    //想要停止线程
    public void stop(){
        mnoitor.interrupt();
    }
}

Java多线程interrupt、interrupted、isInterrupted详解-LMLPHP
这里通过监控线程的打断标记来控制线程停止。

11-10 15:07