如何安全地终止线程、interrupt()、isInterrupted()、interrupted()的区别与使用、Executor 的中断操作


https://github.com/CyC2018/CS-Notes/blob/master/notes/Java%20%E5%B9%B6%E5%8F%91.md#%E4%B8%89%E4%B8%AD%E6%96%AD

一个线程执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束。

如何安全地终止线程

有2种方法可以安全地终止线程:

  1. 使用interrupt()
  2. 利用一个boolean变量来控制是否需要停止任务并终止该线程(推荐)。

interrupt()、isInterrupted()、interrupted()的区别与使用


interrupt()

注意区分interrupted()方法;

public void interrupt()

interrupt()是用于中断线程的,调用该方法的线程的状态将被置为"中断"状态
注意:线程中断仅仅是设置线程的中断状态位,++不会停止线程++。需要用户自己去监视线程的状态为并做处理。


isInterrupted()

isInterrupted()测试线程是否已经中断。线程的 中断状态 不受该方法的影响

public boolean isInterrupted()

interrupted()

public static boolean interrupted()

interrupted()第一次使用返回true,并清除中断标志位,在此之后查询中断状态isInterrupt()都会返回false,第一次返回的true可以跳出循环。第二次以及以后都是返回false。


区别案例

public class InterruptExample {

    private static class MyThread extends Thread {
        @Override
        public void run() {
            while (true) {
                System.out.println(isInterrupted());
                
                //interrupt()并不会中断线程,所以后面的代码会被继续执行;
                interrupt();
                System.out.println(isInterrupted());
                
                //interrupted()第一次返回true,并清除标志位,所以以后查询中断状态返回的都是false
                System.out.println(interrupted());
                System.out.println(isInterrupted()); //false
                break;
            }
            System.out.println("Thread end");
        }
    }

    public static void main(String[] args){
        Thread thread = new MyThread2();
        thread.start();
    }
}

输出

false
true
true   //interrupted()第一次返回true
false
Thread end

注意

  1. 通过调用一个线程的 interrupt()来中断该线程,如果该线程处于阻塞限期等待或者无限期等待状态,那么就会抛出 InterruptedException,从而提前结束该线程。但是不能中断 I/O 阻塞和 synchronized 锁阻塞。

  2. suspend()、resume()和stop()过期了,不建议使用;

public class InterruptExample {

    private static class MyThread1 extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                System.out.println("Thread run");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public static void main(String[] args) throws InterruptedException {
    Thread thread1 = new MyThread1();
    thread1.start();
    thread1.interrupt();
    System.out.println("Main run");
}

由于线程中调用了Thread.sleep()方法,因此会抛出一个 InterruptedException,从而提前结束线程,不执行之后的语句。

Main run
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at InterruptExample.lambda$main$0(InterruptExample.java:5)
    at InterruptExample$$Lambda$1/713338599.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)

使用interrupt()方法终止线程

public class InterruptExample {

    private static class MyThread2 extends Thread {
        @Override
        public void run() {
        //
            while (!isInterrupted()) {
                // ..
            }
            System.out.println("Thread end");
        }
    }
}
public static void main(String[] args) throws InterruptedException {
    Thread thread2 = new MyThread2();
    thread2.start();
    thread2.interrupt();
}
Thread end

使用标志位终止线程

public class InterruptExample {

    private static class MyThread extends Thread {
        private volatile boolean on = true;
        @Override
        public void run() {
            while (on) {
                //todo
            }
        }
        public void cancel(){
            on = false;
        }
    }


    public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();
    }
}


另外

Executor 的中断操作

调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭,但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。

猜你喜欢

转载自blog.csdn.net/qq_43369986/article/details/109061653