在面试中并发编程会经常问到一个问题,那就是如何优雅的暂停一个线程。比如T1线程暂停正在执行的T2线程。
java中提供了stop方法,但是已经被废弃了,原因是这种会直接暂停一个线程,强制执行。但是java采用另一种方式也就是中断,
具体就是其他线程或者本线程调用interrupt(),会将线程的中断标识设置为true。然后线程不断检查这个状态,如果如何就直接退出。
而检查的方式就是通过调用isInterrupted()方法。
public class DemoInterrupt implements Runnable {
@Override
public void run() {
System.out.println("线程开始执行");
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程被中断,退出");
break;
}
System.out.println("程序退出");
}
public static void main(String[] args) throws InterruptedException {
DemoInterrupt demoInterrupt = new DemoInterrupt();
Thread thread = new Thread(demoInterrupt);
thread.start();
Thread.sleep(1000);
System.out.println("线程中断");
thread.interrupt();
System.out.println("执行完毕");
Thread.sleep(1000);
}
}
从执行结果来看,其实interrupt();只是将中断标记设置为true,需要等线程执行完毕,才会停止。
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.jia.interrupt.DemoInterrupt.run(DemoInterrupt.java:17)
at java.lang.Thread.run(Thread.java:748)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
上述的方式其实就是两阶段终止模式,也就是先发送终止指令,然后在执行响应终止指令。
我们知道LockSupport的park和unpark 是用来阻塞线程和解除线程阻塞。那么其实syn中的wait和notify,以及condition的await和singal其实也可以实现线程等待。为什么需要Locksupport,主要是因为syn和lock的阻塞的是整个代码块,而lockSupport阻塞的只是当前的线程,阻塞的粒度更小。
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"线程执行");
LockSupport.park();
System.out.println(Thread.currentThread().getName()+"线程完毕");
});
thread.start();
Thread.sleep(1000);
LockSupport.unpark(thread);
}
public static void park() {
UNSAFE.park(false, 0L);
}
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
本篇文章主要介绍了如何优雅暂停一个线程,以及使用lockSupport进行阻塞和唤醒一个线程。