中断一个线程
在Java
中,如何中断一个线程呢?
其实在以前的版本,有许多方法可以强行直接中断一个线程,比如stop
,suspend
。但是其实这样做是不对的,因为一个线程不应该由其他线程来强制中断或停止。比如一些重要的线程,在一些时候强制中断可能会造成很多损失,因为强制中断的时间不是线程的作者可以预料到的。所以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();
}
}
复制代码