You will always get 1, 2, 4, 3. The 5 will always be after the 1. But where it ends up in relation to the others depends on what queue the whole thing started on.
If this is started from the main queue then 5 will always be between 1 and 2.
Here's why:
This code starts on the main queue. 1 is printed. You then enqueue another block to run asynchronously on the main queue so that block will be run after the current block completes and the main queue gets to the end of the current run loop. The code continues to the next line which is to print 5. The current block ends and the next block on the main queue is run. This is the block of the first call to DispatchQueue.main.async
. As this block runs it prints 2 (so now we have 1 5 2). Another block is enqueued to the main queue just like the last one. The current block continues and prints 4 (so now we have 1 5 2 4). The block ends and the next block on the main queue is run. This is the final block we added. That block runs and it prints 3 giving the final output of 1 5 2 4 3.
If you started on some background queue then 5 can appear anywhere after 1 but for such simple code, the 5 will most likely still appear between 1 and 2 but it can appear anywhere after the 1 in a general case.
Here's why:
This code starts on a background queue. 1 is printed. You then enqueue another block to run asynchronously on the main queue so that block will be run after the current main queue run loop completes. The code continues to the next line which is to print 5. The current block ends. The block added to the main queue is run in parallel to the background queue. Depending on the time of when the block added to the main queue is run in relation to the remaining code on the background queue is run, the output of print("5")
can be intermingled with the prints from the main queue. This is why the 5 can appear anywhere after the 1 when started from the background.
But the simple code in the question will likely always give 1 5 2 4 3 even when started on the background because the code is so short and takes so little time.
Here's some code that puts the 5 elsewhere:
func asyncTest() {
print("1")
DispatchQueue.main.async {
print("2")
DispatchQueue.main.async {
print(3)
}
print("4")
}
for _ in 0...1000 {
}
print("5")
}
DispatchQueue.global(qos: .background).async {
asyncTest()
}
The existence of the loop causes the 5 to take a little longer before it appears which allows the main queue to get executed some before 5 is printed. Without the loop, the background thread executes too quickly so the 5 appears before 2.
If running this test in a playground, add:
PlaygroundPage.current.needsIndefiniteExecution = true
to the top of the playground (just after the imports). You will also need:
import PlaygroundSupport
print("1")
is executed in the main thread or not. – Burkhardt