一、概念
1.1 interrupt方法应用场景
- 用来打断正在阻塞的线程:sleep/wait/join
- 打断正常的线程
1.2 interrupt() 方法
Thread类的实例方法,其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。)作用与正常线程会将中断标记设置为true,但是作用于阻塞线程会将中断标志刷新false(中断标记默认为false,刷新就是重新刷会默认)。
1.3 interrupted() 方法
Thread类的静态方法,作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。
1.4 isInterrupted() 方法
Thread类的实例方法,作用是只测试此线程是否被中断,不清除中断状态。
二、实例
2.1 打断正常线程,不停止线程
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (true){
//让thread线程不断运行
}
});
t.start();
Thread.sleep(1000);//让主线程睡一会
t.interrupt();//打断正在正常运行的thread
System.out.println(t.isInterrupted());
}
}
程序不会停止
2.2 打断正常线程,并停止线程
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (Thread.currentThread().isInterrupted()){
break;
}
});
t.start();
Thread.sleep(1000);//让主线程睡一会
t.interrupt();//打断正在正常运行的thread
System.out.println(t.isInterrupted());
}
}
程序停止
2.3 阻塞线程打断
作用于阻塞线程会将中断标志刷新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();
}
}
这里通过监控线程的打断标记来控制线程停止。