轻松理解Java线程中断机制(Java interrupt)

中断一个线程

Java中,如何中断一个线程呢?

其实在以前的版本,有许多方法可以强行直接中断一个线程,比如stopsuspend。但是其实这样做是不对的,因为一个线程不应该由其他线程来强制中断或停止。比如一些重要的线程,在一些时候强制中断可能会造成很多损失,因为强制中断的时间不是线程的作者可以预料到的。所以stop suspend都被废弃了。

那么,在Java中就不能中断线程了吗?

自然是不是的。Java鼓励大家用另一种方式实现中断。

若要中断一个方法,要手动调用interrupt方法。该方法仅仅是将该线程的中断标识设为true。接着你需要自己写代码不断地检测当前线程的标识位,如果为true 就执行相应的中断处理业务逻辑

让我们首先来了解一下中断线程相关的几个方法。

interrupt()方法,isInterrupted()方法和interrupted()方法

interrupt方法

是实例方法,仅仅是设置线程的中断状态为true,不会停止线程
例子:Thread.currentThread().interrupt();

interrupted方法

是静态方法 判断线程是否被中断 并清除当前中断状态

这个方法做了两件事

①返回当前线程的中断状态

②将当前线程的中断状态设为false
例子:Thread.interrupted();

isInterrupted()方法

实例方法,判断当前线程是否被中断。
例子:Thread.currentThread().isInterrupt();

实现线程中断的例子:

public class test {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                //循环判断是否被打断,如果被打断就执行退出逻辑
                if (Thread.currentThread().isInterrupted()) {
                    //这里是退出逻辑
                    System.out.println("-------即将退出------");
                    break;
                }
                //这里是业务逻辑
                System.out.println("程序在运行");
            }
        });
        t1.start();
        
        //等一秒后新建个线程打断他
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //相当于new Thread(()->t1.interrupt()).start()
        new Thread(t1::interrupt).start();
    }
}
复制代码

但是个这个方法有个问题:

如果线程处于被阻塞状态(sleep wait join等) 在别的线程中调用当前线程对象的interrupt方法,那么线程将退出被阻塞状态,并抛出一个interruptExeption异常。还会清除interrupt标记。

如以下例子:

public class DeadLockDemo{
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("-------即将退出------");
                    break;
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(400);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("程序在运行");
            }
        });
        t1.start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
            //Thread.currentThread.interrupt();
        }
        new Thread(t1::interrupt).start();
    }
}
复制代码

解决方法:在异常里中断,即把注释取消。

思考题:interrupt()方法和isInterrupted()方法的区别

public class DeadLockDemo{
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
        System.out.println(111);
        Thread.currentThread().interrupt();
        System.out.println(222);
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
    }
}
复制代码

这些会输出什么呢

答案:

main---false
main---false
111
222
main---true
main---false
复制代码

还有什么办法实现中断呢?

1.用volatile变量

package com.yswdqz.myblog;
​
​
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
​
​
public class DeadLockDemo{
    private volatile static boolean stop = false;
​
​
    public static void main(String[] args) {
        new Thread(()->{
            while(true){
                if(stop){
                    System.out.println("-------即将退出------");
                    break;
                }
                System.out.println("程序在运行");
            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            stop=true;
        }).start();
    }
}
复制代码

2.用原子操作类 AtomicBoolean

public class DeadLockDemo{
​
    static AtomicBoolean atomicBoolean = new AtomicBoolean();
​
    public static void main(String[] args) {
        new Thread(()->{
            while(true){
                if(atomicBoolean.get()){
                    System.out.println("-------即将退出------");
                    break;
                }
                System.out.println("程序在运行");
            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            atomicBoolean.set(true);
        }).start();
    }
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享