11 线程的中断 interrupt(),InterruptedException 安全的终止线程,线程优雅停止

线程的中断 interrupt,安全的终止线程,线程优雅停止

    • 线程的中断 interrupt(),InterruptedException
    • 安全的终止线程,线程优雅停止
      • 通过boolean变量和interrupt 停止任务终止线程

线程的中断 interrupt(),InterruptedException

中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行了中断操作

中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt() 方法对其进行中断操作。

线程通过检查自身是否被中断来进行响应,线程通过方法isInterrupted()来进行判断是否被中断,

调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。

如果该线程已经处于终结状态,即使该线程被中断过,在调用该线程对象的isInterrupted()时依旧会返回false。

/**
 * 线程中断
 */
public class Interrupted {
    public static void main(String[] args) throws Exception {
        // sleepThread不停的尝试睡眠
        Thread sleepThread = new Thread(new SleepRunner(), "SleepThread");
        sleepThread.setDaemon(true);
        // busyThread不停的运行
        Thread busyThread = new Thread(new BusyRunner(), "BusyThread");
        busyThread.setDaemon(true);
        sleepThread.start();
        busyThread.start();
        // 休眠5秒,让sleepThread和busyThread充分运行
        TimeUnit.SECONDS.sleep(5);
        sleepThread.interrupt();
        busyThread.interrupt();
        System.out.println("SleepThread interrupted is " + sleepThread.isInterrupted());
        System.out.println("BusyThread interrupted is " + busyThread.isInterrupted());
        // 防止sleepThread和busyThread立刻退出
        TimeUnit.SECONDS.sleep(2);

    }

    static class SleepRunner implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class BusyRunner implements Runnable {
        @Override
        public void run() {
            while (true) {
            }
        }
    }
}
//执行结果
SleepThread interrupted is false
BusyThread interrupted is true
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at java.lang.Thread.sleep(Thread.java:340)
	at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
	at com.thread.Interrupted$SleepRunner.run(Interrupted.java:34)
	at java.lang.Thread.run(Thread.java:748)

Process finished with exit code 0

从结果可以看出,抛出InterruptedException的线程SleepThread,其中断标识位被清除了,·而一直忙碌运作的线程BusyThread,中断标识位没有被清除。

安全的终止线程,线程优雅停止

中断状态是线程的一个标识位,而中断操作是一种简便的线程间交互方式,而这种交互方式最适合用来取消或停止任务。

除了中断以外,还可以利用一个boolean变量来控制是否需要停止任务并终止该线程。

通过boolean变量和interrupt 停止任务终止线程

import java.util.concurrent.TimeUnit;

/**
 * 通过boolean变量和interrupt 停止任务终止线程
 */
public class Shutdown {
    public static void main(String[] args) throws Exception {
        Runner one = new Runner();
        Thread countThread = new Thread(one, "CountThread1");
        countThread.start();
        // 睡眠1秒,main线程对CountThread进行中断,使CountThread能够感知中断而结束
        TimeUnit.SECONDS.sleep(1);
        countThread.interrupt();
        Runner two = new Runner();
        countThread = new Thread(two, "CountThread2");
        countThread.start();
        // 睡眠1秒,main线程对Runner two进行取消,使CountThread能够感知on为false而结束
        TimeUnit.SECONDS.sleep(1);
        two.cancel();
    }

    private static class Runner implements Runnable {
        private long i;
        private volatile boolean on = true;

        @Override
        public void run() {
            while (on && !Thread.currentThread().isInterrupted()) {
                i++;
            }
            System.out.println(Thread.currentThread().getName() + " Count i = " + i);
        }

        public void cancel() {
            on = false;
        }
    }
}
//执行结果
CountThread1 Count i = 806103114
CountThread2 Count i = 769049123

Process finished with exit code 0

main线程通过中断操作和cancel()方法均可使CountThread得以终止。

通过标识位或者中断操作的方式能够使线程在终止时有机会去清理资源,而不是武断地 将线程停止,因此这种终止线程的做法显得更加安全和优雅。

/**
 * 示例2
 * 正常情况下是让线程执行完毕后停止
 * 线程停止方法:stop() destroy() 不建议使用功能
 * 还可以通过Interrupt中断操作
 * ThreadStop 一种优雅停止线程的方法
 */
public class ThreadStop implements Runnable {
    private boolean flag = true;

    @Override
    public void run() {
        while (flag){
            System.out.println("ThreadStop...");
        }
        System.out.println("ThreadStop over...");
    }

    public void stop(){
        this.flag=false;
    }

    public static void main(String[] args) {
        ThreadStop threadStop = new ThreadStop();
        new Thread(threadStop).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("Main 线程 " + i);
            if (i == 990){
                threadStop.stop();
            }
        }
    }
}

你可能感兴趣的:(Java,Thread,ThreadPool,线程的中断,interrupt,Interrupted,安全的终止线程,线程优雅停止,Java,多线程)