Created
July 29, 2019 17:10
-
-
Save robertmryan/fc3d924d663e2018740979f26c45de37 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os.log | |
func asynchronousExperiment() { | |
func asynchronousOperation(index: Int, completion: @escaping () -> ()) { | |
os_log("STARTING %d", index) | |
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { | |
os_log("FINISHED %d", index) | |
completion() | |
} | |
} | |
// If using semaphores, you want to make sure you `wait` on a different thread, generally a background thread. | |
// I'll use global worker threads. | |
DispatchQueue.global().async { | |
let semaphore = DispatchSemaphore(value: 4) | |
for i in 0 ..< 100 { | |
semaphore.wait() | |
asynchronousOperation(index: i) { | |
semaphore.signal() | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is designed for controlling the degree of concurrency. In this example, while there are 100 asynchronous tasks, this won’t run more than four at any given time. This is very useful to (a) avoid exhausting the limited number of worker threads; and (b) to constrain peak memory usage, especially in case the
asynchronousOperation
was doing something memory intensive (e.g. downloading and manipulating large images).Frankly, we’d often reach for
OperationQueue
and itsmaxConcurrentOperationCount
when controlling the degree of concurrency, but the above is a GCD solution for the same issue.