我们如何在一个线程中暂停另一个线程的运行?
这里不建议是使用stop方法,使用stop方法虽然可以强行终止正在运行或挂起的线程,但使用stop方法是很危险的。stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁, 其它线程将永远无法获取锁
我们可以使用interrupt方法。在使用该方式时,它并不会像stop方法那样会中断一个正在运行的线程,而是线程会继续运行下去;但会设置该线程的中断状态,即设置为true,线程会不时地检测这个中断标示位,以判断线程是否应该被中断(中断状态是否为true)
public class test2 {
public static void main(String[] args) {
try {
test2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void test2() throws InterruptedException {
Thread t2 = new Thread(()->{
while(true) {
Thread current = Thread.currentThread();
boolean interrupted = current.isInterrupted();
System.out.println(interrupted);
//自己来决定是否停止现场的运行
if(interrupted) {
System.out.println(interrupted);
break;
}
}
}, "t2");
t2.start();
//让主线程睡眠一下
Thread.sleep(500);
t2.interrupt();
}
}
输出结果:
但是当我们打断阻塞中(sleep,wait,join)的线程会让此线程产生一个InterruptedException异常,结束线程的运行。但如果该异常被线程捕获住,该线程依然可以自行决定后续处理(终止运行,继续运行,做一些善后工作等等),而且这个打断阻塞中的线程是会重置标状态为false;
@Slf4j
public class test1 {
public static void main(String[] args) throws InterruptedException {
TwoParseTermination twoParseTermination = new TwoParseTermination();
twoParseTermination.start();
Thread.sleep(3500);
twoParseTermination.stop();
}
}
@Slf4j
class TwoParseTermination {
private Thread monitor;
// 启动线程
public void start() {
monitor = new Thread(() -> {
while (true) {
//拿到当前线程
Thread thread = Thread.currentThread();
if(thread.isInterrupted()) { // 调用 isInterrupted拿到标记值 这个不会清除标记
System.out.println("料理后事 ...");
break; //终止线程
} else {
try {
Thread.sleep(1000);
System.out.println("执行监控的功能 ...");
} catch (InterruptedException e) {
System.out.println("设置打断标记 ...");
//因为捕获异常后标记值变成了false,这里再打断一下,就相当于把这个正在运行的线程给打断了,所以这里的标记值又变成了ture,如果这里不重置这个标记值那么这个线程是会一直运行的
thread.interrupt();
e.printStackTrace();
}
}
}
}, "monitor");
monitor.start();
}
// 终止线程
public void stop() {
monitor.interrupt();
}
}
关于isInterrupted()和Interrupted()方法
这两个方法都可以判断当前线程的打断状态,区别在于:
interrupted()是静态方法,并且会重置当前线程的中断状态(还是false)。而isInterrupted()不会重置当前状态
public class test2 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
thread.interrupt();
Thread.currentThread().interrupt();
System.out.println("第一次"+Thread.interrupted());
System.out.println("第二次"+Thread.interrupted());
}
}
这里我们interrupt了main线程,调用interrupted()方法就会重置为false