Skip to Content

终止模式:两阶段终止模式

Two Phase Termination

在一个线程 T1 中如何“优雅”终止线程 T2?这里的【优雅】指的是给 T2 一个料理后事的机会。

错误思路:

  • 使用线程对象的 stop() 方法停止线程:stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,其它线程将永远无法获取锁
  • 使用 System.exit(int) 方法停止线程:目的仅是停止一个线程,但这种做法会让整个程序都停止

两阶段终止模式:

利用isInterrupted

interrupt 可以打断正在执行的线程,无论这个线程是在 sleep,wait,还是正常运行。

代码实现:

public class TestInterrupt03 { public static void main(String[] args) throws InterruptedException { TwoPhaseTermination t1 = new TwoPhaseTermination(); t1.start(); Thread.sleep(3500); t1.stop(); } } @Slf4j class TwoPhaseTermination { private Thread thread; // 开启监控线程 public void start() { thread = new Thread(() -> { while (true) { Thread current = Thread.currentThread(); if (current.isInterrupted()) { log.debug("料理后事"); break; } try { Thread.sleep(1000); // 情况1:睡眠的时候被打断 log.debug("执行监控记录"); // 情况2:操作的时候被打断 } catch (InterruptedException e) { e.printStackTrace(); // 如果睡眠的时候被打断,打断标记会被重置 // 所以这里重新设置打断标记 current.interrupt(); } } }); thread.start(); } // 停止监控线程 public void stop() { thread.interrupt(); } }

利用停止标记 volatile

// 监控线程 private Thread monitorThread; // 停止标记 private volatile boolean stop = false; // 启动监控线程 public void start() { monitorThread = new Thread(() -> { while (true) { Thread current = Thread.currentThread(); // 是否被打断 if (stop) { log.debug("料理后事"); break; } try { Thread.sleep(1000); log.debug("执行监控记录"); } catch (InterruptedException e) { } } }, "monitor"); monitorThread.start(); } // 停止监控线程 public void stop() { stop = true; monitorThread.interrupt(); }
Last updated on