我从事过Java工作,并且对线程和线程池的工作非常清楚。
我想知道是否有人能解释如何在swift中创建线程池并在线程池中分配空间?
另外,
Dispatch.main.async {
// some code
}
创建新线程还是异步执行任务?
提前致谢=)
答案 0 :(得分:9)
队列和线程是不同的概念。队列是有序的(有时是优先级的)块序列来执行的。作为(大多数)实现细节,必须将块调度到线程上才能执行,但这不是它们的主要观点。
因此Dispatch.main.async
将一个块分派(附加)到主队列。主队列是串行的,有些特殊,因为它承诺也只在主线程上运行(如Paulw11所述)。它还承诺与主要的runloop相关联。理解这个“将一个块附加到队列”概念是至关重要的,因为它对您在队列中设计事物的方式与在线程中设计事物的方式有重大影响。 async
并不意味着“现在开始运行它”。这意味着“坚持在队列中,但不要等待它。”
作为设计如何不同的一个很好的例子,将某些东西放在队列上并不意味着它将永远运行(即使没有错误或死锁)。暂停队列以使其停止调度块是可能且有用的。可以将队列绑定到其他队列,以便当队列“调度”某些内容时,它只是将其放入另一个队列而不是执行它。对于与“在后台运行的东西”无关的队列,你可以做很多事情。您可以将完成处理程序附加到块。您可以使用组等待块集合。 GCD是一种思考并发性的方法。并行性只是一个附带的好处。 (对这个概念的一个很好的讨论是Concurrency is not parallelism by Rob Pike。它在Go中,但这些概念仍然适用。)
如果在主队列上运行时调用Dispatch.main.async
,则该块绝对肯定不执行,直到当前块完成。在UIKit和AppKit中,“当前块完成”通常意味着“您从操作系统调用的方法返回”。虽然没有以这种方式实现,但您可以假装每次从操作系统调用时,它都被包含在Dispatch.main.async
的调用中。
这也是您不得从主队列中调用Dispatch.main.sync
(注意sync
)的原因。该块将等待您返回,并且您将等到块完成。经典的僵局。
通常,线程池不是您在iOS中的业务。这是一个实现细节。有时候出于性能原因需要考虑它,但是如果你想的太多,你可能会错误地设计你的并发性。
如果你来自Java,你肯定想在并发编程指南中阅读Migrating Away From Threads。它是如何在队列中重新思考基于线程的模式的权威资源。
答案 1 :(得分:3)
您的代码会在主队列(Dispatch.main
)上对代码块进行排队,并在执行代码之前立即返回(.async
)。
您无法控制队列使用哪个线程。即使您创建了自己的队列:
let serialQueue = DispatchQueue(label: "queuename")
serialQueue.async {
...
}
您不知道您的代码将在哪个线程上运行。
更新
正如Paulw11在评论中所说,
...如果在主队列上调度任务,则保证在主线程上执行。如果在任何其他队列上调度任务,则不知道它将在哪个线程上执行;它可以在主线程或其他线程上执行。