我有两个以不同时间间隔运行的计时器,其中一个被添加到运行循环中。
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
// do some stuff
}
let timer2 = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
// do some other stuff
}
RunLoop.current.add(timer2, forMode: RunLoop.Mode.common)
我有一个条件,要求两个计时器的执行逻辑不会同时运行,因为它们都在修改相同的数据结构。
这已经被iOS保证了吗? 如果没有,我能确保这种情况发生的最佳方法是什么?
只要你把计时器安排在同一RunLoop
上,你就是安全的。RunLoop
始终只与一个线程相关联,因此块将在该线程上执行。因此,它们永远不会同时开火。 但是,如果您将它们安排在两个不同的RunLoop
实例上,情况就会有所不同。 我不确定你说一个计时器只添加到RunLoop
是什么意思.如果不向RunLoop
添加计时器,则根本不会触发。
你的代码不符合你所描述的: APIscheduledTimer(withTimeInterval
将计时器隐式添加到运行循环中。您不得自行将计时器添加到运行循环中。 因此,两个计时器都在运行循环上运行。
我建议使用DispatchSourceTimer
和自定义DispatchQueue
。默认情况下,队列是串行的,并作为 FIFO(先进先出(工作。串行队列保证任务不会同时执行。
计时器在创建后将挂起。您必须调用activate()
(或在iOS 9及更低版本中resume()
(才能启动计时器,例如在viewDidLoad
class Controller : UIViewController {
let queue = DispatchQueue(label: "myQueue")
lazy var timer1 : DispatchSourceTimer = {
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.schedule(deadline:.now() + 1.0, repeating: 1.0)
timer.setEventHandler(handler: eventHandler1)
return timer
}()
lazy var timer2 : DispatchSourceTimer = {
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.schedule(deadline:.now() + 0.5, repeating: 0.5)
timer.setEventHandler(handler: eventHandler2)
return timer
}()
override func viewDidLoad() {
super.viewDidLoad()
timer1.activate()
timer2.activate()
}
func eventHandler1() {
DispatchQueue.main.async {
// do stuff on the main thread
}
}
func eventHandler2() {
DispatchQueue.main.async {
// do stuff on the main thread
}
}
}
计时器属性被延迟声明以避免可选,事件处理程序闭包(() -> Void
(作为标准方法实现。
如果您同时安排两个计时器,则无法确保它们会同时触发。
你可以通过以下方式确保它,在定时器1的火块中安排计时器2,等等...
如果您需要确保计时器块的串行执行,而不管计时器本身被调度在哪里,您应该创建自己的串行队列并将计时器的工作分派到其中:
let timerQueue = DispatchQueue(label: "timerQueue")
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
timerQueue.async {
// do stuff
}
}
let timer2 = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
timerQueue.async {
// do some other stuff
}
}