2

Every Thread has its own RunLoop, how DispatchQueue interact with them? Is DispatchQueue using RunLoop to dispatch task to Thread or do it by another way?

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Grigorii
  • 43
  • 6

1 Answers1

4

Any thread can have a run loop, but, nowadays, in practice, only the main thread does.

When you create a thread manually, it will not have a run loop. When you call RunLoop.current, the name suggests that it is grabbing the thread’s run loop, suggesting that it always will have one. But in reality, when you call current, it will return the run loop if one is already there, and if not, it creates a RunLoop for you. As the docs say:

If a run loop does not yet exist for the thread, one is created and returned.

And if you do create a run loop, you have to spin on it yourself (as shown here; and that example is over-simplified). But we don’t do that very often anymore. GCD has rendered it largely obsolete.

At a high level, GCD has pools of worker threads, one pool per quality of service (QoS). When you dispatch something via GCD to any queue (other than targeting the main queue), it grabs an available worker thread of the appropriate QoS, performs the task, and when done, marks the worker thread as available for future dispatched tasks. No run loop is needed (or desired) for these worker threads.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks for your answer! But what is worker thread and who and how put it to sleep when nothing to do? – Grigorii Jan 21 '22 at 07:08
  • For example, code like this `DispatchQueue.global().async { print(RunLoop.current) }` will always print some not null runloop, therefore threads from thread pool have a runloops. For what if it no needed? – Grigorii Jan 21 '22 at 07:17
  • “what is worker thread?” ... It is simply a thread created by GCD on our behalf. And it has a “pool” of them so that it doesn't constantly create and destroy them (which is computationally expensive, i.e., slow), but effectively just sets them aside so that they're waiting and ready for when you need one again. “who and how put it to sleep when nothing to do?” ... libdispatch/GCD does all of that for you, with no effort required on your part. – Rob Jan 21 '22 at 07:29
  • “For example, code like this `DispatchQueue.global().async { print(RunLoop.current) }` will always print some not null” ... Correct. But like I said, that doesn't mean there was already a runloop there. As the quoted docs say, `current` actually _creates_ a run loop when there wasn't one there already (such as your GCD example). Bottom line, except for very rare situations, just forget about run loops in the context of GCD. It doesn't use them and they're simply not needed/relevant in the context of GCD. – Rob Jan 21 '22 at 07:29
  • ok, thank you! I'm not going to use runloop with GCD, i just trying to figure out how it works under the hood – Grigorii Jan 21 '22 at 07:58