Java中如何暂停Runnable或线程?wait()抛异常解析与解决
线程wait()抛出IllegalMonitorStateException问题解析
问题重现
你定义的Runnable类:
package com.example.testtest; public class FootballRunner implements Runnable { @Override public void run() { while (true) { System.out.println("Running " + Thread.currentThread().getId() + " " + Math.random()); try { Thread.sleep(1_000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
主类代码:
package com.example.testtest; public class TestScheduling { public static void main(String[] args) throws InterruptedException { FootballRunner footballRunner = new FootballRunner(); Thread t1 = new Thread(footballRunner, "one"); t1.start(); t1.wait(); } }
运行后抛出异常:
Exception in thread "main" java.lang.IllegalMonitorStateException: current thread is not owner at java.base/java.lang.Object.wait(Native Method) at java.base/java.lang.Object.wait(Object.java:338) at com.example.testtest.TestScheduling.main(TestScheduling.java:8)
1. "current thread is not owner" 是什么意思?
wait()是Object类的核心方法,它的调用有严格前提:当前线程必须持有该对象的监视器锁(即通过synchronized关键字获取的锁)。
你在main线程中直接调用t1.wait(),但main线程从未通过synchronized(t1)代码块获取t1对象的锁,所以JVM会抛出IllegalMonitorStateException,提示的"current thread is not owner"直白来说就是:你当前的线程(main)不是t1这个对象监视器锁的持有者,没有资格调用它的wait()方法。
另外要明确:wait()的作用是让持有锁的线程自己进入等待状态,并释放锁,它不是用来暂停其他线程的工具,你的用法完全误解了这个方法的用途。
2. 如何正确实现线程t1的暂停?
Thread类的suspend()方法已被废弃(容易导致死锁,锁无法释放),推荐用以下两种标准方式:
方法一:利用线程中断机制
通过中断标志位控制线程循环,同时正确响应中断异常:
package com.example.testtest; public class FootballRunner implements Runnable { @Override public void run() { // 循环前检查线程中断状态 while (!Thread.currentThread().isInterrupted()) { System.out.println("Running " + Thread.currentThread().getId() + " " + Math.random()); try { Thread.sleep(1_000); } catch (InterruptedException e) { // 捕获中断后,重置中断状态(因为sleep会清除中断标志) Thread.currentThread().interrupt(); break; // 退出循环,终止线程 } } System.out.println("线程t1已停止"); } }
主类中调用interrupt()触发中断:
package com.example.testtest; public class TestScheduling { public static void main(String[] args) throws InterruptedException { FootballRunner footballRunner = new FootballRunner(); Thread t1 = new Thread(footballRunner, "one"); t1.start(); // 让main线程等待3秒后,中断t1 Thread.sleep(3000); t1.interrupt(); } }
方法二:使用volatile标志位控制
定义一个volatile修饰的布尔变量(保证多线程下的可见性),通过修改该变量来终止线程循环:
package com.example.testtest; public class FootballRunner implements Runnable { // volatile保证变量修改对其他线程立即可见 private volatile boolean isRunning = true; // 提供外部调用的停止方法 public void stopThread() { isRunning = false; } @Override public void run() { while (isRunning) { System.out.println("Running " + Thread.currentThread().getId() + " " + Math.random()); try { Thread.sleep(1_000); } catch (InterruptedException e) { throw new RuntimeException(e); } } System.out.println("线程t1已停止"); } }
主类中调用stopThread()方法:
package com.example.testtest; public class TestScheduling { public static void main(String[] args) throws InterruptedException { FootballRunner footballRunner = new FootballRunner(); Thread t1 = new Thread(footballRunner, "one"); t1.start(); Thread.sleep(3000); footballRunner.stopThread(); // 触发线程停止 } }
内容的提问来源于stack exchange,提问作者ilhan
相关产品推荐
相关产品推荐

