Java线程wait与布尔值监控:厨房烤箱多线程实现疑问
解决多线程厨房模拟中烤箱烘烤状态的线程安全问题
这个场景太典型了——我之前做过一个餐厅后厨模拟的项目,也碰到过几乎一模一样的问题!核心痛点就是要确保烤箱的烘烤周期是要么完整跑完X时长且全程开启,要么中途被关闭就立刻返回失败,而普通布尔值在多线程下的可见性和原子性问题刚好踩中了这个坑。下面给你两个实用的解决方案,根据你的项目复杂度选就行:
方案一:用原子类实现轻量级状态检查
把标记烤箱状态的普通boolean换成AtomicBoolean,它能保证状态的读写都是线程安全的,同时我们可以用循环等待+实时检查的方式,确保中途状态变化能立刻被感知:
import java.util.concurrent.atomic.AtomicBoolean; public class Oven { private final AtomicBoolean isOvenOn = new AtomicBoolean(true); public boolean bakeDish(long bakeTimeMs) { // 先确认烤箱当前是开启的,才启动烘烤 if (!isOvenOn.get()) { return false; } long startTime = System.currentTimeMillis(); try { // 循环等待,每次间隔100ms检查一次状态,避免忙等 while (System.currentTimeMillis() - startTime < bakeTimeMs) { Thread.sleep(100); // 中途发现烤箱关闭,直接返回未熟透 if (!isOvenOn.get()) { return false; } } // 最后再确认一次状态,防止最后一刻被关闭 return isOvenOn.get(); } catch (InterruptedException e) { // 线程被中断时,保留中断状态并返回失败 Thread.currentThread().interrupt(); return false; } } // 关闭烤箱的方法,线程安全 public void turnOffOven() { isOvenOn.set(false); } }
这个方案的优点是实现简单,不需要复杂的锁机制,适合状态变更不频繁的场景。
方案二:用锁+条件变量实现精准同步
如果你的项目需要更高效的状态响应(比如烤箱关闭时立刻唤醒烘烤线程,不需要等待sleep结束),可以用ReentrantLock配合Condition来实现,所有状态操作都在锁的保护下,完全避免并发问题:
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Oven { private final ReentrantLock ovenLock = new ReentrantLock(); private final Condition ovenTurnedOff = ovenLock.newCondition(); private boolean isOvenOn = true; public boolean bakeDish(long bakeTimeMs) { ovenLock.lock(); try { if (!isOvenOn) { return false; } // 等待指定时长,或者直到烤箱被关闭的信号唤醒 boolean interruptedByShutdown = ovenTurnedOff.await(bakeTimeMs, TimeUnit.MILLISECONDS); // 如果返回true,说明是被关闭信号唤醒的,返回未熟透;否则是等待超时,再确认状态 return !interruptedByShutdown && isOvenOn; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } finally { ovenLock.unlock(); } } public void turnOffOven() { ovenLock.lock(); try { isOvenOn = false; ovenTurnedOff.signalAll(); // 唤醒所有正在烘烤的线程 } finally { ovenLock.unlock(); } } }
这个方案的优势是响应更及时,而且状态的一致性得到了绝对保障,适合并发场景复杂、状态变更频繁的项目。
避坑提醒
- 绝对不要用普通
boolean存状态:多线程下非原子的读写会导致可见性问题——比如烤箱已经关闭,但烘烤线程还读取到旧的true值,返回错误的“熟透”结果。 - 别直接用
Thread.sleep(bakeTimeMs)后再检查状态:这段时间内状态被修改的话,线程无法及时响应,只能等到sleep结束才发现,完全不符合需求。 - 处理
InterruptedException时一定要重置中断状态:避免上层逻辑丢失中断信号,导致后续线程行为异常。
内容的提问来源于stack exchange,提问作者JamesRichardson
相关产品推荐
相关产品推荐

