【问题标题】:Swift 3 DispatchGroup single success DispatchWorkItemSwift 3 DispatchGroup 单成功 DispatchWorkItem
【发布时间】:2017-08-22 01:08:45
【问题描述】:

这是交易。我正在尝试在树上行走。但想同时这样做。所以每次我走到一个节点上时,我都需要同时遍历它的所有节点等等。 但。我不想等待整个 DispatchGroup 完成以获得结果,因为这就像 Big O 中最坏的情况。 相反,我想取消所有其他 DispatchWorkItems 并在后续的一个中为它们留下组。试图通过计算结束的任务来做到这一点。显然我做错了什么或误解了如何使用它。 下面的代码只是为了示例和测试这个想法而编写的。 考虑现实世界的情况是,在 DispatchWorkItem 中,您可以递归调用树的当前节点的另一个 handle 函数。

func handle(completion: @escaping (Int) -> Void) {
    var result: Int = 0


    var count = 7
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "q", attributes: .concurrent)

    var items = [DispatchWorkItem]()

    let item1 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...1000 { continue }
        count -= 1
        group.leave()
        print("left 1")
    }
    let item2 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...2000 { continue }
        count -= 1
        group.leave()
        print("left 2")
    }
    let item3 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...6000 { continue }
        count -= 1
        group.leave()
        print("left 3")
    }
    let item4 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...3000 { continue }
        result = 42

        items.forEach { $0.cancel() }

        for _ in 0..<count {
            group.leave()
        }

        print("ok; left 4")
    }
    let item5 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...50000 { continue }
        count -= 1

        group.leave()
        print("left 5")
    }
    let item6 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...6000 { continue }
        count -= 1
        group.leave()
        print("left 6")
    }
    let item7 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...8000 { continue }
        count -= 1
        group.leave()
        print("left 7")
    }

    items.append(item1)
    items.append(item2)
    items.append(item3)
    items.append(item4)
    items.append(item5)
    items.append(item6)
    items.append(item7)

    for item in items {
        group.enter()
        queue.async(execute: item)
    }

    group.notify(queue: queue) { 
        return
    }
}

test() {
    handle { result in
        print(result)
    }

}

【问题讨论】:

  • “走树”? “遍历所有节点”?它们是什么意思?
  • 树 - 数据结构。作为二叉树,但对子节点的数量没有限制
  • 顺便说一下,我不知道您的各个节点的密集程度,但请记住,并行处理的性能增益很容易被协调所有这些线程。确保您对每个分派的代码都进行了足够的处理。

标签: ios swift swift3 concurrency grand-central-dispatch


【解决方案1】:

您不能同时从多个线程读取和写入计数变量。您需要在计数上放置一个互斥锁。您尝试从多个线程访问和/或更改计数时遇到不稳定的情况。此外,您应该将其设计为根本不需要计数。

【讨论】:

    【解决方案2】:

    一些想法:

    1. 如果你想取消一个耗时的任务,你需要定期检查isCancelled。见https://stackoverflow.com/a/38372384/1271826

    2. 如果要从多个线程更新 countitems,则必须同步该交互(例如,使用锁或专用串行队列)。 IntArray 不是线程安全的,因此您必须自己管理。

    3. 跟踪count 并使用DispatchGroup 并跟踪您自己收集的DispatchWorkItem 引用将需要一些工作。操作队列让你摆脱所有这些。话虽如此,如果需要最大效率,那么也许您希望留在调度队列中,但这只是更多的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      相关资源
      最近更新 更多