2017-04-26 228 views
3

我工作在Java上,并且非常清楚线程和线程池的工作情况。线程池:DispatchQueue.main.async

我想知道是否有人可以解释如何创建线程的工作,并在线程池中分配空间在swift?

此外,没有

Dispatch.main.async { 
// some code 
} 

创建一个新的线程或异步执行任务?

预先感谢=)

回答

3

您的代码队列在主队列(Dispatch.main)的代码块,并立即(.async)返回,在执行代码之前。

您无法控制队列使用哪个线程。即使你创建了自己的队列:

let serialQueue = DispatchQueue(label: "queuename") 
serialQueue.async { 
    ... 
} 

你不知道你的代码将在哪个线程上运行。


更新:

由于正确地Paulw11的评论指出,

...如果你在主队列调度任务,这是保证在主线程上执行。如果您在任何其他队列上派发任务,则不知道它将在哪个线程上执行;它可能会在主线程或其他线程上执行。

+5

有一点,如果您在主队列上派发任务,则保证在主线程上执行。如果您在任何其他队列上派发任务,则不知道它将在哪个线程上执行;它可能会在主线程或其他线程上执行。 – Paulw11

+0

@ Paulw11正确。更新了答案。 – shallowThought

6

队列和线程是单独的概念。队列被排序(有时是优先级)块序列执行。作为(大部分)实现细节,块必须被调度到线程才能执行,但这不是它们的主要观点。

因此Dispatch.main.async将一个块调度(追加)到主队列中。主队列是串行的,并且有点特别,因为它可以在主线程上独占运行(正如Paulw11所指出的那样)。它也承诺与主要的runloop相关联。理解这种“将队列附加到队列”的概念是至关重要的,因为它对你在队列中设计事物的方式以及你在线程中设计事物的方式有重大影响。 async并不意味着“现在就开始运行”。这意味着“坚持在队列中,但不要等待它。”

作为设计如何不同的一个很好的例子,将一些东西放在队列中并不意味着它会运行(即使没有错误或死锁)有史以来运行。暂停队列以停止调度块是可能的和有用的。将队列绑定到其他队列是可能的,这样当队列“计划”某些内容时,它就会将其放入另一个队列中,而不是执行它。有很多事情可以通过与“在后台运行事件”无关的队列来完成。您可以将完成处理程序附加到块。您可以使用组来等待块的集合。 GCD是考虑并发性的一种方式。并行性只是一个副作用。 (这个概念的一个很好的讨论是Concurrency is not parallelism by Rob Pike它在Go中,但这些概念仍然适用。)

如果你调用Dispatch.main.async主队列运行时,则该块是绝对肯定执行,直到当前块结束。在UIKit和AppKit中,“当前块完成”通常意味着“您从OS调用的方法返回”。虽然没有以这种方式实现,但您可以假装每次从OS调用它时,都会调用Dispatch.main.async

这也是您为什么决不能从主队列中调用Dispatch.main.sync(注意sync)的原因。该块会等待你回来,你会等到块完成。经典的僵局。

通常,线程池不是iOS中的业务。这是一个实现细节。有时你需要考虑性能方面的原因,但是如果你对此有太多的想法,那么你可能会错误地设计你的并发性。

如果您来自Java,您一定要在并发编程指南中阅读Migrating Away From Threads。它是如何重新考虑队列中基于线程的模式的权威资源。