如何从其他线程发送中断信号?共享监视器线程终止方案问询
Java线程相关问题解答
1. 如何从一个线程向另一个线程发送中断信号?
Java里的线程中断是协作式的——不是直接硬终止线程,而是给目标线程递一个“该停手了”的信号,让线程自己决定怎么响应。具体操作步骤是这样的:
- 第一步:调用目标线程实例的
interrupt()方法。这个方法会把目标线程的中断状态位设为true,但不会直接打断线程的运行。 - 第二步:目标线程要主动检测中断状态,常见两种方式:
- 调用
Thread.currentThread().isInterrupted():这个方法会返回当前线程的中断状态,而且不会清除状态位,适合循环里做判断。 - 如果线程在执行可中断阻塞方法(比如
Thread.sleep()、Object.wait()、Thread.join()),调用interrupt()会让这些方法抛出InterruptedException,同时线程的中断状态位会被清除。这时候如果需要保留中断状态,可以在catch块里再次调用Thread.currentThread().interrupt()。
- 调用
举个简单的实战例子:
// 干活的目标线程 class WorkerThread extends Thread { @Override public void run() { // 循环执行任务,同时盯着中断信号 while (!Thread.currentThread().isInterrupted()) { System.out.println("正在处理任务..."); try { Thread.sleep(1000); } catch (InterruptedException e) { // 捕获到中断,重置状态然后退出循环 Thread.currentThread().interrupt(); break; } } System.out.println("收到中断信号,结束工作"); } } // 测试代码 public class InterruptDemo { public static void main(String[] args) throws InterruptedException { WorkerThread worker = new WorkerThread(); worker.start(); // 让线程跑3秒后发中断信号 Thread.sleep(3000); worker.interrupt(); } }
2. 两个线程共用监视器实例,唤醒等待线程并终止流程的解决方案
这种场景下,核心是用共享终止标志配合wait()/notifyAll()实现协作,还要注意处理虚假唤醒的坑。具体方案如下:
首先在ABC类里加一个volatile修饰的终止标志(保证多线程下的可见性),然后修改同步方法doProcess(),让等待的线程每次被唤醒后先检查终止状态:
示例代码:
class ABC { // volatile保证一个线程修改后,其他线程能立刻读到最新值 private volatile boolean shouldTerminate = false; // 业务条件:比如任务是否完成 private boolean taskCompleted = false; public synchronized void doProcess() { try { // 必须用循环包裹wait()!防止虚假唤醒(没收到通知就醒来) while (!taskCompleted && !shouldTerminate) { System.out.println(Thread.currentThread().getName() + " 条件不满足,进入等待"); wait(); } // 被唤醒后先判断是否要终止 if (shouldTerminate) { System.out.println(Thread.currentThread().getName() + " 收到终止指令,退出处理"); return; } // 正常执行业务逻辑 System.out.println(Thread.currentThread().getName() + " 执行正常业务流程"); taskCompleted = true; } catch (InterruptedException e) { // 处理中断,重置状态后退出 Thread.currentThread().interrupt(); System.out.println(Thread.currentThread().getName() + " 被中断,结束处理"); } } // 触发终止的方法:设置标志+唤醒所有等待线程 public synchronized void triggerTermination() { shouldTerminate = true; notifyAll(); // 用notifyAll比notify安全,确保所有等待的线程都能收到通知 } } // 测试线程1 class Thread1 extends Thread { private ABC o; public Thread1(ABC o) { this.o = o; } @Override public void run() { o.doProcess(); } } // 测试线程2 class Thread2 extends Thread { private ABC o; public Thread2(ABC o) { this.o = o; } @Override public void run() { // 模拟一些前置处理 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 触发终止流程"); o.triggerTermination(); } } // 测试类 public class ThreadMonitorDemo { public static void main(String[] args) { ABC o = new ABC(); Thread1 t1 = new Thread1(o); Thread2 t2 = new Thread2(o); t1.start(); t2.start(); } }
关键注意点:
volatile修饰终止标志:避免线程间的状态不可见问题。wait()必须在循环中:虚假唤醒是Java线程机制的正常现象,所以每次唤醒后都要重新校验条件和终止标志。- 优先用
notifyAll():如果有多个线程等待同一个监视器,notify()可能只唤醒其中一个,notifyAll()能确保所有等待线程都收到通知,不会遗漏。
内容的提问来源于stack exchange,提问作者Deepu--Java
相关产品推荐
相关产品推荐

