티스토리 뷰

반응형

안녕하세요 :) Zedd입니다.

DispatchQueue를 더 깊이 알아봅시다. 안깊을수도 있음 ㅎ_ㅎ..

DispatchQueue의 QoS와 workItem의 QoS, 그리고 Dispatch Group에 대해 알아볼게요.

개념말고;; 사용법ㅎㅎ

읽기전에 <GCD - Dispatch Queue사용법 (1)> 을 읽고오시는 걸 추천


GCD - Dispatch Queue사용법 (2)



QoS를 또 이 글에서 적는 건 아닌 것 같아서 따로 정리 ㄱ

<Prioritize Work with Quality of Service Classes

문서 중간중간 이해가 안가는 부분들이 몇개 있었지만..가장 중요한건 QoS가 뭐가 있냐!!!! 그게 제일 중요한 것 같아요. 그리고 각각의 QoS가 어떤 곳?..어떨 때 쓰여야 하는지 뭐 예를들어 사용자와 계속 상호작용을 해야하는지, 아니면 안해도 되는지 뭐 그런것들? 그런것들만 알면 QoS에 대해....뭐 다 아는거라고 할 수 있을 것 같....!!

그럼 DispatchQueue의 QoS를 알아봅시다.


일단 Queue자체에 QoS를 달리 주면 어떻게 될까요


let zeddQueue = DispatchQueue(label: "zedd" ,qos: .userInitiated)

let alanQueue = DispatchQueue(label: "alanWalker", qos: .utility)


zeddQueue.async {

            for i in 1...5 {

                print("👻 \(i)")

            }

        }

alanQueue.async {

            for i in 100...105{

                print("🌕 \(i)")

            }

        }


zeddQueue👻에 더 중요한? 더 높은 QoS를 주었습니다! 어떻게 될까요? 





ZeddQueue👻가 대부분의 경우 먼저 실행되고 있어요. 

지금 두 Queue가 Serial이긴 하지만, task가 하나씩 있기 때문에 의미없고, async로 돌렸음에도 불구하고 ZeddQueue👻가 먼저 실행되는 것이죠. 

alanQueue도 ZeddQueue와 똑같이 userInitiated를 주게되면, 매번...실행결과가 달라지긴 하지만,(물론 위 결과도 매번 달라지긴 하지만)

조금 균형있게? 나오게 됩니다.

오옹

ㅇㅋㅇㅋ

그럼 이제 workItem을 보면 되는 부분


일단 workItem에 QoS를 줄건데, 그럼 이제 queue하나만 필요하겠죠? 그 하나의 Queue안에서 뭐 QoS에 따른 

실행순서를 결정할 것이니까요.


let myQueue = DispatchQueue(label: "myQueue")

let zeddItem = DispatchWorkItem(qos: .userInitiated) {

          for i in 1...5 {

                print("👻 \(i)")

            }

}

let alanItem = DispatchWorkItem(qos: .userInitiated) {

            for i in 100...105 {

               print("🌕 \(i)")

            }

}

myQueue.async(execute: zeddItem)

myQueue.async(execute: alanItem)


흐음 이게 코드가 길어지니까 가독성이 조금 떨어지네요..

아무튼 이렇게 하면..어떻게 될 것 같으신가요 ㅎ



네..그렇습니다..무슨 workItem을 “먼저” 넣었냐에 따라 다르겠죠? 왜냐!!! 지금 하나의 queue에서 작업중인데, queue만들 때 attributes로 concurrent안줬죠ㅎ;; 여기서 QoS를 뭘 어떻게 다르게 줘도 먼저 넣은게 먼저 서비스를 받고 Serial이기 때문에..........먼저 넣은게 끝나야 다음 task가 실행을 하게 되니까 ㅎㅎ;



오 gist깐지..암튼..이렇게 queue를 concurrent로 바꿔줍시다.

그리고 지금 QoS가 다른거 보이죠?!?! Zedd. 즉 유령👻이 더 QoS가 높으니 유령이 먼저 실행되면 좋겠는데요




앗 왼쪽꺼 캡쳐에 머지..암튼 대체로 이런 양상을 띈..? 유령이 먼저 실행되게 됩니다.

concurrent임에도 불구하고!!!!

둘다 qos를 똑같이 주면



당연히 뭐 이런 패턴? 둘다 골고루 나오는 그런 걸 텐데.. QoS를 다르게 주니 Operation에서의 addDependency준 것 처럼....뭔가 할 수 있을 것 같네요. 



operation은 각 개별 작업에 대해 priority를 줄 수 있고, GCD에서는 queue에 대한 priority만 줄 수 있다고 봤었는데..역시 직접 써봐야 하는군요.

아닌가..? GCD에서도 Queue에 대한 우선순위와 작업에 대한 우선순위 둘 다 줄 수 있는...거 아닌가요?!?!?!?

흠 


아!! 또 <Prioritize Work with Quality of Service Classes글에서 배운 QoS promotion rule도 잠깐 볼 수 있겠죠. 우리는 queue에 QoS를 안줬으니까




요게 적용이 되겠네요...? 


아무튼 DispatchGroup으로 ㄱㄱ

한번도 안써봤....


Dispatch Group



일단 문서를 보면, 

dispatch Group은 작업의 synchronization을 집계(?)(aggregate)를 허용합니다. 이를 사용하여 서로 다른 queue에서 실행될 수 있지만, 여러개의 다른 작업 item을제출(submit)하고, 모든 작업이 완료되면, 이를 추적(track)할 수 있습니다. 이 동작은 지정된 모든 작업이 완료될 때 까지 기다려야 하는 경우, 유용 할 수 있습니다.



let myGroup = DispatchGroup()


일단 이렇게 DispatchGroup을 하나 만들고


myQueue.async(group: myGroup) {

            for i in 100...105 {

                print("🌕 \(i)")

            }

        }

myQueue.async(group: myGroup) {

            for i in 1...5 {

                print("👻 \(i)")

            }

        }


나의 task를 어느 group에서 할지 지정 할 수 있어요.

이렇게 하면..!


myGroup.notify(queue: myQueue) {

            print("end!")

        }


내 DispatchGroup에 대해서 notify라는 메소드를 호출 할 수 있는데, 파라미터로 큐를 받네요.

아니 왜이렇게 GCD메소드에는 특히 Swift는 왜이렇게 문서에 Discription이 없지?

아무튼 이렇게 하면, 저 Group에 들어간 task들이 모두 끝나면!!! notify가 호출되어 end!가 출력되게 됩니다.





다~~ 실행하고 뭔가를 해주고 싶을 때 유용하겠네요!

후행클로져가 있으니..........굉장히 꿀인 부분



이렇게도 할 수 이씀 ㅎㅎ 물론 notify도 저 notify 클로져 안에 있어야 합니당. 바깥에 있으면 위에 있던 작업에 대해서 불림ㅁ

이러면 이렇게 하면 저의 completionHandler들이 조금 정리될...수...있..을 것 같네요.

아주 잘 만든 것 같음


반응형

'iOS' 카테고리의 다른 글

iOS ) UIResponder  (5) 2018.05.26
iOS ) AVKit과 AVFoundation  (1) 2018.05.13
iOS ) Prioritize Work with Quality of Service Classes  (0) 2018.04.29
iOS ) GCD - Dispatch Queue사용법 (1)  (5) 2018.04.29
iOS ) 왜 main.sync를 하면 안될까  (9) 2018.04.29