需要一些关于调度队列,线程和NSRunLoop的说明 [英] need some clarifications about dispatch queue, thread and NSRunLoop

查看:122
本文介绍了需要一些关于调度队列,线程和NSRunLoop的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我所知道的事情。理解:

全局队列是一个并发队列,可以将任务分派给多个线程。执行任务的顺序无法保证。例如:

Global queue is a concurrent queue which can dispatch tasks to multiple threads. The order of executing task is not guaranteed. e.g.:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), {
 for (int i; i<10; i++) {
  doTask()
 }
})

如果我想发送到串行队列,我可以使用

If I want to dispatch to serial queue, I can use

dispatch_async(dispatch_queue_create("my.serial.queue", nil) {
  ...
}

每次只有一个任务被分派到一个线程并被执行。订单是FIFO。

each time only one task is dispatched to a thread & get executed. The order is FIFO.

=====我感到困惑和不完全理解=======


  1. 主线程有一个NSRunLoop,在主线程中循环任务.I我想知道调度队列和运行循环之间的关系是什么?
    我能理解它,如果将任务调度到主线程,主线程的NSRunLoop获取调度任务并执行它吗?

  1. The main thread has a NSRunLoop, looping tasks in main thread. I am wondering what is the relation ship between dispatch queue and run loop? Can I understand it like, if dispatching a task to main thread, the main thread's NSRunLoop get the dispatched task and execute it?

将任务调度到多个的全局队列怎么样?读? iOS / OSX系统是否自动创建线程,还为每个线程创建NSRunLoop?然后每个线程中的运行循环从全局队列&获取调度任务。执行它?

What about global queue which dispatching tasks to multiple threads? Does iOS/OSX system automatically create not only the threads, but also create NSRunLoop for each thread? and then the run loop in each thread get the dispatched task from global queue & execute it?

谁知道线程?执行 dispatch_async() dispatch_sync()函数知道要调度任务的线程或执行队列知道要调度任务的线程?

Who knows the thread? Do dispatch_async() and dispatch_sync() function know to which thread to dispatch task or does the queue knows to which thread to dispatch task?

有没有办法从调度中获取线程的NSRunLoop对象(调度任务的对象)以编程方式排队? (这个问题与问题3有关)

Is there a way to get NSRunLoop object of the thread(to which the task is dispatched) from dispatch queue programmatically? (this question is related with question 3)


推荐答案


  1. 主线程的运行循环有一个步骤,它运行在主队列上排队的任何块。如果您想了解运行循环的详细信息,可能会发现此答案非常有用。

GCD为并发队列创建线程。一个线程没有运行循环,直到第一次在线程上运行的东西要求线程的运行循环,此时系统为该线程创建一个运行循环。但是,只有当该线程上的某些内容要求它运行时(通过调用 - [NSRunLoop run] CFRunLoopRun 或类似的)。大多数线程,包括为GCD队列创建的线程,都没有运行循环。

GCD creates the threads for concurrent queues. A thread doesn't have a run loop until the first time something running on the thread asks for the thread's run loop, at which point the system creates a run loop for the thread. However, the run loop only runs if something on that thread then asks it to run (by calling -[NSRunLoop run] or CFRunLoopRun or similar). Most threads, including threads created for GCD queues, never have a run loop.

GCD管理线程池,当需要运行块时(因为它被添加到某个队列中),GCD选择运行该块的线程。 GCD的线程选择算法主要是一个实现细节,除了总是选择添加到主队列的块的主线程。 (注意,GCD有时也会将主线程用于添加到其他队列的块。)

GCD manages a pool of threads and, when it needs to run a block (because it was added to some queue), GCD picks the thread on which to run the block. GCD's thread-choosing algorithm is mostly an implementation detail, except that it will always choose the main thread for a block that was added to the main queue. (Note that GCD will also sometimes use the main thread for a block added to some other queue.)

您只能获得主线程的运行循环(使用 + [NSRunLoop mainRunLoop] CFRunLoopGetMain )或当前线程的运行循环(使用 + [NSRunLoop currentRunLoop] CFRunLoopGetCurrent )。如果您需要某个任意线程的运行循环,您必须找到一种方法在该线程上调用 CFRunLoopGetCurrent 并以安全,同步的方式将其返回值传回线程。

You can only get the run loop of the main thread (using +[NSRunLoop mainRunLoop] or CFRunLoopGetMain) or the run loop of the current thread (using +[NSRunLoop currentRunLoop] or CFRunLoopGetCurrent). If you need the run loop of some arbitrary thread, you must find a way to call CFRunLoopGetCurrent on that thread and pass its return value back across threads in a safe, synchronized way.

请注意 NSRunLoop 界面不是线程安全,但是 CFRunLoop 接口 是线程安全的,所以如果你需要访问另一个线程的运行循环,你应该使用 CFRunLoop interface。

Please note that the NSRunLoop interface is not thread safe, but the CFRunLoop interface is thread safe, so if you need to access another thread's run loop, you should use the CFRunLoop interface.

另请注意,您可能不应在GCD队列上运行的块内运行很长时间的运行循环,因为您正在占用一个GCD期望控制的线程。如果你需要长时间运行一个运行循环,你应该为它启动自己的线程。您可以在 中查看此示例。 _legacyStreamRunLoop CFStream.c中的函数。请注意它如何使专用线程的运行循环在名为 sLegacyRL 的静态变量中可用,它在 dispatch_semaphore_t

Also note that you should probably not run a run loop for very long inside a block running on a GCD queue, because you're tying up a thread that GCD expects to control. If you need to run a run loop for a long time, you should start your own thread for it. You can see an example of this in the _legacyStreamRunLoop function in CFStream.c. Note how it makes the dedicated thread's run loop available in a static variable named sLegacyRL, which it initializes under the protection of a dispatch_semaphore_t.

这篇关于需要一些关于调度队列,线程和NSRunLoop的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆