优先用 sleep() 实现秒级延时,usleep() 仅用于亚秒级且需加函数存在性判断和兜底;Web 请求中禁用长 sleep(),header("Refresh") 是客户端跳转而非服务端延时;PHP 无原生 async/await,延时调试需排查 max_execution_time、OPcache、框架超时及 disable_functions。

sleep() 和 usleep() 到底该用哪个?
PHP 里实现延时,最直接的就是 sleep() 和 usleep()。前者单位是秒,后者是微秒(1 秒 = 1,000,000 微秒)。新手常误以为 usleep(1000000) 就等于 sleep(1) —— 理论上对,但实际执行中,usleep() 在部分系统(尤其是 Windows + Apache)下可能精度极差,甚至卡住或提前返回。
实操建议:
- 需要秒级停顿(比如防刷、轮询间隔),无条件选
sleep(); - 需要亚秒级控制(如模拟毫秒级重试退避),优先用
usleep(1000 * $ms),但必须加兜底:if (function_exists('usleep')) { ... } else { sleep(1); }; - 别在 Web 请求中用
sleep(5)这类长延时——它会占满一个 PHP-FPM worker 或 Apache 线程,直接拖垮并发能力。
为什么 header("Refresh: 3") 不算真延时?
header("Refresh: 3; url=next.php") 是浏览器端跳转,PHP 脚本本身立刻执行完毕,不阻塞。它和 sleep() 完全是两回事:前者是 HTTP 响应头触发的客户端行为,后者是服务端进程挂起。
常见误用场景:
立即学习“PHP免费学习笔记(深入)”;
- 想“等 2 秒再查数据库”,却用了 Refresh → 实际是立刻查了,然后让浏览器 2 秒后刷新页面,数据还是旧的;
- 用 Refresh 模拟倒计时 → 用户禁用 JS 或刷新页面就丢失状态;
- 搭配
session_start()后用 Refresh,可能因 session 缓存导致数据没写入就跳走了。
async/await 在 PHP 里不存在,别被误导
PHP 8.1+ 支持 fibers,但没有原生 async/await 语法。网上有些“PHP 异步延时”示例,本质是用 pcntl_fork() 或 curl_multi 模拟,并非真正异步。对新手来说,这些方案复杂度远超需求,还容易引发僵尸进程、资源泄漏等问题。
务实做法:
- Web 场景要“延迟执行某件事”,用消息队列(如 Redis +
LPUSH/BRPOP)或定时任务(crontab+ CLI 脚本); - CLI 脚本需串行等待(如发完邮件等 1 秒再发下一封),老老实实用
sleep(); - 别为了“看着高级”硬套协程库(如 Swoole 的
co::sleep()),除非你已明确要切到协程模型并承担调试成本。
延时调试时最容易忽略的陷阱
本地开发用 sleep(1) 看起来正常,上线后突然失效或变慢,大概率是以下原因:
- PHP 配置里
max_execution_time小于总延时时间 → 直接Fatal error: Maximum execution time of X seconds exceeded; - 使用了 OPcache 且脚本被缓存,修改了
sleep()参数却没清缓存 → 表现为“改了代码没生效”; - 在 Laravel 或 ThinkPHP 等框架中,
sleep()被包裹在中间件或事件监听器里,而框架自身有超时机制(如 Laravel 的timeout配置); - 某些共享主机禁用
sleep()函数(检查disable_functions列表),报错是Warning: sleep() has been disabled for security reasons。
真正麻烦的不是怎么写延时,而是延时发生在哪里、被谁管着、有没有人在背后悄悄 kill 掉它。











