Dispatch Queue
대부분의 UI는 메인스레드에서 작동을 해야한다.
메인스레드가 중지하게되면 모든 작업들이 일시적으로 멈춰버리기 때문에 이를 해결하기위해 다른 스레드에 코드를 맡기고 결과값을 메인 스레드가 처리하게끔 한다.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var finishLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func action1(_ sender: Any) {
simpleClosure {
//DispatchQueue.main.async { ,이쪽에 기입해도 됨
self.finishLabel.text = "끝"
}
}
func simpleClosure(completion: @escaping () -> Void) {
DispatchQueue.global().async { //메인 스레드가 아닌 다른 스레드에게 작업을 맡김
for index in 0..<10 {
Thread.sleep(forTimeInterval: 0.1) //0.1 초씩 늦게 실행 되게 함, 메인스레드 자체를 멈춰버리기 때문에 모든게 멈춰버림
print(index)
}
DispatchQueue.main.async { //메인 스레드에게 completion 클로저 수행을 맡김
completion()
}
}
}
어떤 작업을 하는 것들을 묶어서 표현하고 싶다면 그룹으로 묶으면 된다.
@IBAction func action2(_ sender: Any) {
let dispatchgroup = DispatchGroup() //dispatch 그룹을 형성 (비었음)
let queue1 = DispatchQueue(label: "q1") //queue1은 작업자
let queue2 = DispatchQueue(label: "q2")
let queue3 = DispatchQueue(label: "q3")
queue1.async(group: dispatchgroup) { //dispatch 그룹에 queue1 을 넣고 작업을 실행한다.
for index in 0..<10 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
}
queue2.async(group: dispatchgroup) {
for index in 10..<20 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
}
queue3.async(group: dispatchgroup) {
for index in 20..<30 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
}
dispatchgroup.notify(queue: DispatchQueue.main) { //그룹에 작업이 끝나면 출력한다. , main스레드에서 queue가 작업을 실행하게함
print("끝")
}
}
}
queue1, 2, 3들은 메인이 아닌 새로운 스레드를 생성한 것이다. 결과적으로 ui를 출력하기 위해서는 메인 스레드로 정보를 옮겨야하고, 그냥 단순 계산같은것은 여기서 다 처리할 수 있다.
만약
queue1.async(group: dispatchgroup) {
DispatchQueue.global().async { //이렇게 하면 다른 스레드에게 이 작업을 맡겨버림
for index in 10..<20 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
}
}
}
이렇게 다른 스레드에게 작업을 맡긴다면 notify는 작업이 끝난줄 알고 종료해버린다. 그럴때
dispatchGroup.enter() //작업을 시작함
dispatchGroup.leave() //작업을 끝냄
이런식으로 작업의 시작과 끝을 알릴 수 있다.
async와 다르게 작업을 다 처리할 때 까지는 여러개의 작업자든 한개이건 상관없이 작동을 멈춘다.
가장 중요한 작업을 실행할 때 사용하게 된다.
-같은 큐에 같은 큐가 들어감
queue1.sync {
for index in 0..<10 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
------------------------------- 여기까지 실행되고 deadlock이 걸려버림
queue1.sync {
for index in 10..<20 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
}
}
바깥에 queue1이 실행되는 중이기 때문에 내부에 sync때문에 오류가 발생함
이런 이유로 메인 스레드는 끝나는게 없기 때문에 sync를 사용할 경우 반드시 에러가 발생한다.
작업을 수행하는 우선순위를 설정한다. 절대적으로 보장하지는 않는다.
qos: DispatchQoS <- command+control 우클릭해서 들어가면 순위를 볼 수 있다.
queue2.async(group: dispatchgroup, qos: .background) { //우선 순위 가장 낮음
for index in 10..<20 {
Thread.sleep(forTimeInterval: 0.1)
print(index)
}
}