并发队列问题 - iOS/Swift
Concurrent Queue Issue - iOS/Swift
在我的程序中,我需要两个任务在后台同时运行。为此,我使用了如下并发队列,
let concurrentQueue = DispatchQueue(label: "concurrentQueue", qos: .utility, attributes: .concurrent)
concurrentQueue.async {
for i in 0 ..< 10{
print(i)
}
}
concurrentQueue.async {
for i in (0 ..< 10).reversed(){
print(i)
}
}
这里我需要这样的输出,
0
9
1
8
2
7
3
6
4
5
5
4
6
3
7
2
8
1
9
0
但是我得到的是,
我参考了下面的教程,以便在 Swift 3
中了解有关并发队列的一些基本知识
https://www.appcoda.com/grand-central-dispatch/
有人可以告诉我我的代码有什么问题吗?否则这是我应该得到的结果吗?还有其他方法可以完成我的工作吗?任何帮助将不胜感激。
您的代码示例没有任何问题。这是将两个任务提交到并发队列的正确语法。
问题在于您一定会同时看到它们 运行。有两个问题可能会对此产生影响:
第一个分派的任务可以 运行 如此之快,以至于它恰好在第二个任务开始之前完成。如果你把它们放慢一点,你会看到你的并发行为:
let concurrentQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".concurrentQueue", qos: .utility, attributes: .concurrent)
concurrentQueue.async {
for i in 0 ..< 10 {
print("forward: ", i)
Thread.sleep(forTimeInterval: 0.1)
}
}
concurrentQueue.async {
for i in (0 ..< 10).reversed() {
print("reversed:", i)
Thread.sleep(forTimeInterval: 0.1)
}
}
您永远不会 sleep
在生产代码中,但出于教学目的,它可以更好地说明问题。
您也可以省略 sleep
调用,只需大幅增加数量(例如 1_000
或 10_000
),您可能会开始看到并发处理的发生。
您的设备可能是资源受限的,因此无法运行并发执行代码。设备的 CPU 个内核数量有限,无法执行 运行 个并发任务。仅仅因为您将任务提交到并发队列,并不意味着该设备能够 运行 同时执行这两个任务。这取决于硬件以及该设备上 运行ning 的其他内容。
顺便说一下,请注意您可能会在模拟器上看到不同的行为(它使用的是您的 Mac 的 CPU,这可能是 运行 宁许多其他任务)比在设备上。如果您尚未在实际设备上测试此行为,您可能需要确保进行测试。
另请注意,您说的是 "need" 输出以在两个队列之间交替 print
语句。虽然教程中的屏幕快照表明这应该是预期的,但您绝对不能保证会是这种情况。
如果你真的需要它们来回交替,你必须添加一些机制来协调它们。您可以使用信号量(我不愿意建议,因为它们是问题的常见来源,尤其是对于新开发人员而言)或具有依赖性的操作队列。
也许你可以尝试使用信号量。
let semaphore1 = DispatchSemaphore(value: 1)
let semaphore2 = DispatchSemaphore(value: 0)
concurrentQueue.async {
for i in 0 ..< 10{
semaphore1.wait()
print(i)
semaphore2.signal()
}
}
concurrentQueue.async {
for i in (0 ..< 10).reversed(){
semaphore2.wait()
print(i)
semaphore1.signal()
}
}
在我的程序中,我需要两个任务在后台同时运行。为此,我使用了如下并发队列,
let concurrentQueue = DispatchQueue(label: "concurrentQueue", qos: .utility, attributes: .concurrent)
concurrentQueue.async {
for i in 0 ..< 10{
print(i)
}
}
concurrentQueue.async {
for i in (0 ..< 10).reversed(){
print(i)
}
}
这里我需要这样的输出,
0
9
1
8
2
7
3
6
4
5
5
4
6
3
7
2
8
1
9
0
但是我得到的是,
我参考了下面的教程,以便在 Swift 3
中了解有关并发队列的一些基本知识
https://www.appcoda.com/grand-central-dispatch/
有人可以告诉我我的代码有什么问题吗?否则这是我应该得到的结果吗?还有其他方法可以完成我的工作吗?任何帮助将不胜感激。
您的代码示例没有任何问题。这是将两个任务提交到并发队列的正确语法。
问题在于您一定会同时看到它们 运行。有两个问题可能会对此产生影响:
第一个分派的任务可以 运行 如此之快,以至于它恰好在第二个任务开始之前完成。如果你把它们放慢一点,你会看到你的并发行为:
let concurrentQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".concurrentQueue", qos: .utility, attributes: .concurrent) concurrentQueue.async { for i in 0 ..< 10 { print("forward: ", i) Thread.sleep(forTimeInterval: 0.1) } } concurrentQueue.async { for i in (0 ..< 10).reversed() { print("reversed:", i) Thread.sleep(forTimeInterval: 0.1) } }
您永远不会
sleep
在生产代码中,但出于教学目的,它可以更好地说明问题。您也可以省略
sleep
调用,只需大幅增加数量(例如1_000
或10_000
),您可能会开始看到并发处理的发生。您的设备可能是资源受限的,因此无法运行并发执行代码。设备的 CPU 个内核数量有限,无法执行 运行 个并发任务。仅仅因为您将任务提交到并发队列,并不意味着该设备能够 运行 同时执行这两个任务。这取决于硬件以及该设备上 运行ning 的其他内容。
顺便说一下,请注意您可能会在模拟器上看到不同的行为(它使用的是您的 Mac 的 CPU,这可能是 运行 宁许多其他任务)比在设备上。如果您尚未在实际设备上测试此行为,您可能需要确保进行测试。
另请注意,您说的是 "need" 输出以在两个队列之间交替 print
语句。虽然教程中的屏幕快照表明这应该是预期的,但您绝对不能保证会是这种情况。
如果你真的需要它们来回交替,你必须添加一些机制来协调它们。您可以使用信号量(我不愿意建议,因为它们是问题的常见来源,尤其是对于新开发人员而言)或具有依赖性的操作队列。
也许你可以尝试使用信号量。
let semaphore1 = DispatchSemaphore(value: 1)
let semaphore2 = DispatchSemaphore(value: 0)
concurrentQueue.async {
for i in 0 ..< 10{
semaphore1.wait()
print(i)
semaphore2.signal()
}
}
concurrentQueue.async {
for i in (0 ..< 10).reversed(){
semaphore2.wait()
print(i)
semaphore1.signal()
}
}