用策略模式封装等待行为,将忙轮询重构为可配置、可替换、可测试的WaitStrategy接口,如SleepWaitStrategy通过sleep()释放CPU并响应中断,配合模板方法与工厂实现自动适配场景。

用 sleep() 组合设计模式告别忙轮询,核心不是“加个 sleep 就行”,而是把“等待”从逻辑里抽出来,变成可配置、可替换、可测试的行为。忙轮询(while (!ready) { /* do nothing */ })本质是 CPU 空转,它浪费资源、掩盖真实依赖、难以中断、无法适应不同场景——而这些,恰恰是策略模式(Strategy Pattern)最擅长解决的问题。
把“等待方式”定义成接口
先明确一点:真正需要抽象的,不是“要不要等”,而是“怎么等”。比如:
- 后台任务希望休眠 100ms 再查一次(省电)
- 实时数据通道希望 yield 让出 CPU,但不休眠(低延迟)
- 关键控制指令必须 busy-wait 直到硬件就绪(确定性)
把这些行为统一建模为一个策略接口,例如 Java 中:
interface WaitStrategy {
void await(Predicate<boolean> condition, long timeoutMs);
}</boolean>
这样,业务代码不再写 while(!flag),而是调用 waitStrategy.await(() -> flag, 5000) —— 具体怎么等,由实现类决定。
用 sleep() 实现“休眠型”策略
SleepWaitStrategy 是最常用也最安全的落地方式。它不空转,不占 CPU,适合绝大多数非实时场景:
class SleepWaitStrategy implements WaitStrategy {
private final long intervalMs;
<pre class="brush:php;toolbar:false;">SleepWaitStrategy(long intervalMs) {
this.intervalMs = Math.max(1, intervalMs);
}
@Override
public void await(Predicate<boolean> condition, long timeoutMs) {
long start = System.currentTimeMillis();
while (!condition.test(true)) {
if (System.currentTimeMillis() - start > timeoutMs) {
throw new TimeoutException("Wait timed out");
}
try {
Thread.sleep(intervalMs); // ✅ 真正释放 CPU
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}</boolean>
}
注意两点:一是每次 sleep() 前都检查条件,避免多睡一次;二是必须响应中断,不能吞掉 InterruptedException。
组合工厂 + 模板方法,让策略自动适配场景
硬编码策略选择会回到 if-else 屎山。更合理的方式是按上下文自动装配:
- 通过配置(如 Spring Profile 或 YAML)指定当前环境用哪种策略
- 用模板方法封装“等待-重试-超时”流程,子类只负责实现
doWait() - 在初始化阶段注入具体策略,业务层完全无感
例如一个通用重试器:
abstract class RetryableOperation<t> {
protected abstract T execute() throws Exception;
protected abstract WaitStrategy getWaitStrategy();
<pre class="brush:php;toolbar:false;">public T runWithRetry(int maxRetries, long baseDelayMs) {
for (int i = 0; i false, baseDelayMs * (long) Math.pow(2, i));
}
}
return null;
}
}
子类只需决定“用 sleep 还是 yield”,不用重复写重试循环和异常处理逻辑。
为什么这比单纯加 sleep() 更可靠?
单独在 while 循环里加 Thread.sleep(10) 看似简单,但容易踩坑:
- 没处理
InterruptedException,导致线程无法被优雅中断 - 没做超时保护,条件永远不满足就会无限休眠
- 休眠间隔写死,无法随环境(开发/压测/生产)动态调整
- 多个地方复制粘贴,一处改、处处改,维护成本高
而策略模式 + sleep() 的组合,把“等待”变成了显式契约、可单元测试的组件,也自然支持熔断、退避、日志埋点等增强能力。










