Mastering Concurrency in iOS - Part 2 (Dispatch Queues, Quality of Service, Attributes)
메인 스레드
를 사용메인 스레드
가 아닌 다른 스레드를 사용DispatchQueue.main.async {
let threadCondition = Thread.isMainThread ? "Execution in Main Thread" : "Execution in Global Thread"
print("Main Queue: \(threadCondition)")
}
DispatchQueue.global(qos: .background).async {
let threadCondition = Thread.isMainThread ? "Execution in Main Thread" : "Execution in Global Thread"
print("Global Queue: \(threadCondition)")
}
qos
를 적용한다 할지라도 메인 스레드는 오로지 메인 큐에서만 사용 가능DispatchQueue.global(qos: .background).async {
for i in 100...200 {
print(i)
}
}
DispatchQueue.global(qos: .userInteractive).async {
for i in 0...99 {
print(i)
}
}
let a = DispatchQueue(label: "A")
let b = DispatchQueue(label: "B", attributes: [.concurrent, .initiallyInactive])
b.setTarget(queue: a)
b.async {
print("Testing Thread Activation")
}
b.activate()
a.async {
for i in 0...5 {
print(i)
}
}
a.async {
for i in 6...10 {
print(i)
}
}
b.async {
for i in 11...15 {
print(i)
}
}
b.async {
for i in 16...20 {
print(i)
}
}
.initiallyInactive
를 어트리뷰트로 설정하지 않고 이후 b
스레드에 타겟을 설정한다면 크래쉬 → 액티브한 상태의 스레드의 타겟 큐는 변경 불가능하기 때문에 비활성화 상태에서 타겟 큐를 설정, 이후 해당 스레드를 활성화해야 함var value: Int = 20
let serialQueue = DispatchQueue(label: "com.queue.Serial")
func doAsyncTaskInSerialQueue() {
for i in 1...3 {
serialQueue.async {
if Thread.isMainThread {
print("task running in main thread")
} else {
print("task running in global thread")
}
guard
let imageURL = URL(string: "https://www.nintenderos.com/wp-content/uploads/2020/04/anime-pokemon-pikachu.jpg"),
let _ = try? Data(contentsOf: imageURL) else { return }
print("\(i) finished downloading")
}
}
}
doAsyncTaskInSerialQueue()
serialQueue.async {
for i in 0...3 {
value = i
print("\(value) in next block")
}
}
print("last line in playground")
/*
task running in global thread
last line in playground
1 finished downloading
task running in global thread
2 finished downloading
task running in global thread
3 finished downloading
0 in next block
1 in next block
2 in next block
3 in next block
*/
var value: Int = 20
let serialQueue = DispatchQueue(label: "com.queue.Serial")
func doSyncTaskInSerialQueue() {
for i in 1...3 {
serialQueue.sync {
if Thread.isMainThread {
print("task running in main thread")
} else {
print("task running in global thread")
}
guard
let imageURL = URL(string: "https://www.nintenderos.com/wp-content/uploads/2020/04/anime-pokemon-pikachu.jpg"),
let _ = try? Data(contentsOf: imageURL) else { return }
print("\(i) finished downloading")
}
}
}
doSyncTaskInSerialQueue()
serialQueue.sync {
for i in 0...3 {
value = i
print("\(value) in next block")
}
}
print("last line in playground")
/*
task running in main thread
1 finished downloading
task running in main thread
2 finished downloading
task running in main thread
3 finished downloading
0 in next block
1 in next block
2 in next block
3 in next block
last line in playground
*/
sync
블럭을 통해 실행한 디스패치 큐로 인해 메인 큐에서 실행되는 태스크는 현재 블락된 상황 → 즉 메인 스레드는 유휴 상태(idle)이므로 시스템은 이러한 메인 스레드를 활용하고자 함 → sync
블럭 내부에서 사용되는 스레드가 글로벌이 아니라 메인 스레드가 되는 까닭var value: Int = 20
let concurrentQueue = DispatchQueue(label: "com.queue.Concurrent", attributes: .concurrent)
func doAsyncTaskInConcurrentQueue() {
for i in 1...3 {
concurrentQueue.async {
if Thread.isMainThread {
print("task running in main thread")
} else {
print("task running in global thread")
}
guard
let imageURL = URL(string: "https://www.nintenderos.com/wp-content/uploads/2020/04/anime-pokemon-pikachu.jpg"),
let _ = try? Data(contentsOf: imageURL) else { return }
print("\(i) finished downloading")
}
}
}
doAsyncTaskInConcurrentQueue()
concurrentQueue.async {
for i in 0...3 {
value = i
print("\(i) in next block")
}
}
print("last line in playground")
/*
task running in global thread
last line in playground
task running in global thread
task running in global thread
0 in next block
1 in next block
2 in next block
3 in next block
3 finished downloading
1 finished downloading
2 finished downloading
*/
var value: Int = 20
let concurrentQueue = DispatchQueue(label: "com.queue.Concurrent", attributes: .concurrent)
func doSyncTaskInConcurrentQueue() {
for i in 1...3 {
concurrentQueue.sync {
if Thread.isMainThread {
print("task running in main thread")
} else {
print("task running in global thread")
}
guard
let imageURL = URL(string: "https://www.nintenderos.com/wp-content/uploads/2020/04/anime-pokemon-pikachu.jpg"),
let _ = try? Data(contentsOf: imageURL) else { return }
print("\(i) finished downloading")
}
}
}
doSyncTaskInConcurrentQueue()
concurrentQueue.sync {
for i in 0...3 {
value = i
print("\(i) in next block")
}
}
print("last line in playground")
/*
task running in main thread
1 finished downloading
task running in main thread
2 finished downloading
task running in main thread
3 finished downloading
0 in next block
1 in next block
2 in next block
3 in next block
last line in playground
*/