【问题标题】:Serial OperationQueue with Operations synchronizing timer and sleep具有同步定时器和睡眠的操作的串行操作队列
【发布时间】:2020-01-17 21:11:15
【问题描述】:

我有一个串行 OperationQueue,其操作调用 usleep。我这样做是因为操作执行块与需要重复直到指定时间的 Timer 同步。

例如,将 3 个操作添加到一个队列,其中 maxconcurrent 设置为 1。每个操作都有一个计时器,该计时器重复到未来 10 秒。在触发第一个操作的此计时器时,下一行代码是 usleep(10 秒)。 10 秒后计时器完成,线程唤醒。下一个操作开始。这是通过设计和工作完成的,但是,我担心睡眠线程的含义。线程是否有可能正在处理一些其他代码,上下文切换来处理操作,然后休眠很长时间,暂停其他执行。 swift 是否知道在操作休眠时让线程执行其他块?

【问题讨论】:

    标签: swift multithreading concurrency sleep operation


    【解决方案1】:

    swift 是否知道在操作休眠时让线程执行其他块?

    也许这只是一个措辞问题,但线程 被阻塞,直到睡眠(和后续任务)完成,所以它不会被用来做任何其他事情。但是,当线程处于休眠状态时,核心可以切换上下文以让其他线程运行,即使运行该操作的线程已被占用。

    所以使用usleep(或者我可能使用Thread.sleep(forTimeInterval: 10))避免了阻塞核心的问题,但它仍然阻塞了线程。并且线程相当有限(例如此时为 64)。因此,特别是如果您可能在任何给定时间进行大量此类操作,从而冒着耗尽有限线程的风险,我可能会建议您也避免阻塞线程。 (再说一次,如果你使用 1 的 maxConcurrentOperationCount,只要你不做其他可能会占用线程的事情,它可能不会太严重。)

    例如,我可能定义一个异步Operation 子类,而不是休眠,我可能只是asyncAfter(或使用计时器)将操作完成到10 秒后。这样也没有线程被阻塞。或者我可能会考虑其他模式来解决更广泛的问题。不知道您要解决的更广泛的问题很难说。

    【讨论】:

    • 您好 Rob,感谢您的彻底回复。如果线程 A 用于执行一些异步 http 请求,那么在线程 B(一个完全不同的线程)上,我创建上述操作队列并向其添加操作。核心是否有可能在线程 A 上进行上下文切换以执行操作。或者它是否通过 gcd 创建了一个全新的线程。如果是前者,在操作中不能长时间休眠暂停 http 请求或者核心是否知道线程 A 处于睡眠状态,而另一个线程继续执行 http 任务。非常感谢我和我的公司。
    • 首先,GCD 很少创建新线程。它利用了一个小的“工作线程”池,最大限度地减少了一直启动新线程的开销。每次它需要一个线程时,它都会从该池中抓取一个(不保证它会抓取哪一个)。其次,一个线程上的sleep 将阻塞其线程,但不会影响来自单独线程的异步请求。唯一的例外是,例如 URLSession 使用的串行队列:你永远不想在一个完成处理程序或委托方法中休眠,因为这会阻塞所有其他 URLSession 委托方法。
    • 所有这些都已经说了,我通常建议永远睡在一个人的代码中。这是对资源的浪费。当我看到睡眠调用时,通常是代码味道更深层次的问题。我会重构它以消除任何睡眠呼叫。如果你这样做,它完全消除了某些类别的潜在问题。我严重怀疑你在一个线程上的睡眠会影响另一个线程(但不能说没有code sample),但只要消除睡眠调用,不仅你的代码更高效,而且消除了所有疑虑。
    • 我正在尝试创建一种振动和延迟模式。我有一个以毫秒为单位的交替振动持续时间和延迟列表 [200,30,100,30]。如果在列表中找到“0”,则取消所有当前振动。我有一个如上所述的串行操作队列。因为执行顺序很重要,所以我找不到使用 asyncafter 或 timer 的解决方案,这不会增加代码的复杂性。使用新的 Core Haptic,这很容易,但是对于旧版本的 iOS,我必须自己处理这种模式。
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多