方法概述
-
这里我们先说interrupt方法应用场景:
1:用来打断正在阻塞的线程:sleep/wait/join
2:打断正常的线程 -
interrupt()
其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。)作用与正常线程会将中断标记设置为true,但是作用于阻塞线程会将中断标志刷新false(中断标记默认为false,刷新就是重新刷会默认)。 -
interrupted()
作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。 -
isInterrupted()
作用是只测试此线程是否被中断 ,不清除中断状态。
实战讲解
正常线程打断
正常线程会将中断标记设置为true
线程仍会继续运行。
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
while (true){
//让thread线程不断运行
}
});
thread.start();
Thread.sleep(1000);//让主线程睡一会
thread.interrupt();//打断正在正常运行的thread
System.out.println(thread.isInterrupted());
}
输出
这里我们换成这种代码可以在打断后让线程结束(用中断标记):
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
while (true){
Boolean flag=Thread.currentThread().isInterrupted();//得到当前线程的打断标记
if (flag){
break;//如果被打断过则跳出结束了此线程的操作
}
}
});
thread.start();
Thread.sleep(1000);//让主线程睡一会
thread.interrupt();//打断正在正常运行的thread
System.out.println(thread.isInterrupted());
}
阻塞线程打断
作用于阻塞线程会将中断标志刷新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());
}
输出:
这里我们发现输出的是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());
}
这里我们就是false,因为这里在thread1.interrupt();前让主线程睡一会,让thread1有时间进入到睡眠的状态,这样才会造成我们想要的在睡眠阻塞中打断。
两阶段终止设计模式
这里涉及到在线程T1里如何就“优雅”的终止线程T2(例如上面在主线程中如何优雅终止线程thread)
优雅:指的不是直接杀死T2,而是给T2一个料理后事的机会。直接杀死不好,stop方法现在也被废弃,就是不让大家直接杀死线程。
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();
}
}
这里通过监控线程的打断标记来控制线程停止。