在后台队列上休眠线程时,我也得到大约 120 毫秒的时间:
import Foundation
DispatchQueue.global(qos: .background).async {
let timeStart = Date()
usleep(20 * 1000) // 20 ms
let timeEnd = Date()
let timeDif = timeEnd.timeIntervalSince(timeStart) * 1000
print("start: \(timeStart), end: \(timeEnd), dif: \(timeDif)")
exit(0)
}
CFRunLoopRun()
输出:
start: 2018-04-03 00:10:54 +0000, end: 2018-04-03 00:10:54 +0000, dif: 119.734048843384
但是,使用默认 QoS,我的结果始终接近 20 毫秒:
import Foundation
DispatchQueue.global(qos: .default).async {
let timeStart = Date()
usleep(20 * 1000) // 20 ms
let timeEnd = Date()
let timeDif = timeEnd.timeIntervalSince(timeStart) * 1000
print("start: \(timeStart), end: \(timeEnd), dif: \(timeDif)")
exit(0)
}
CFRunLoopRun()
start: 2018-04-03 00:12:15 +0000, end: 2018-04-03 00:12:15 +0000, dif: 20.035982131958
因此,QoS 似乎.background
导致了您所看到的行为。虽然我不直接知道为什么会这样,但推测操作系统在唤醒标记有后台 QoS 的睡眠线程方面可能会有些松懈,这似乎并不牵强。事实上,这就是Apple 的文档所要说的:
服务质量 (QoS) 类允许您对要由 NSOperation、NSOperationQueue、NSThread 对象、调度队列和 pthread(POSIX 线程)执行的工作进行分类。通过将 QoS 分配给工作,您可以表明其重要性,并且系统会对其进行优先级排序并相应地对其进行调度。例如,系统比可以推迟到更佳时间的后台工作更早地执行用户发起的工作。在某些情况下,系统资源可能会从优先级较低的工作中重新分配并分配给优先级较高的工作。
您的背景工作被“推迟到更佳时间”的可能性似乎是对您所看到的行为的合理解释。