[Swift] Concurrency Programming - 3

Martin Kim·2022년 2월 10일
0

swift-concurrency

목록 보기
3/4

DispatchQueue의 생성자

  • DispatchQueue를 초기화 하는 생성자 다음과 같다.
convenience init(label: String,
                 qos: DispatchQoS = .unspecified,
                 attributes: DispatchQueue.Attributes = [],
                 autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency = .inherit,
                 target: DispatchQueue? = nil)

label

  • 디버깅 환경에서 추적하기 위해 작성하는 String 값
  • 식별자

qos

  • Quality of Service의 약자로 실행될 Task의 우선 순위를 정해준다.
  • 반드시 일이 처리 되는 '순서'를 정해주는 것이 아니라 무엇에 더 '에너지를 많이 투자할까'를 결정하는 것에 가깝다.
  • 일이 처리되는 순서를 결정하는 요소는 아니지만 어느정도 영향을 미칠 수는 있다.
  • 더 많은 에너지를 쏟는다는 것은 더 많은 스레드, 더 많은 전력을 할당한다는 뜻이다
  • QoS로 우선 순위를 결정하는 일은 꼭 정량적인 수치나 절대적인 값을 할당하는 개념이 아니다. GCD에서 스레드 관리는 시스템이 해주기 때문이다.
  • 수행 작업에 적절한 QoS를 할당하면 앱이 더 반응적(responsive)이고 보다 효율적인 에너지 사용이 가능해진다.

복붙복붙

  • 1️⃣ User-interactive

    • main thread에서 작업하며, 사용자 인터페이스 새로고침, 애니메이션 등 사용자와 상호작용하는 작업에 할당. 작업이 빠르게 수행되지 않으면, 유저 인터페이스는 멈춘다. 반응성(responsiveness)과 성능(performance)에 중점!
  • 2️⃣ User-initiated

    • 문서를 열거나 버튼을 클릭해 액션을 수행하는 것처럼 빠른 결과를 요구하는 유저와의 상호작용 작업에 할당. 몇 초 이내의 짧은 시간 내에 수행해야하는 작업으로 반응성과 성능에 중점.
  • 3️⃣ Default

    • QoS를 할당해주지 않을 경우 기본값으로 사용되며 User Initiate와 Utility의 중간 수준의 레벨.
  • 4️⃣ Utility

    • 데이터를 읽거나 다운로드하는 작업처럼 작업이 완료되는데에 어느정도 시간이 걸리거나 즉각적인 결과가 요구되지 않는 작업에 할당. 반응성, 성능, 에너지 효율의 밸런스에 중점.
  • 5️⃣ Background

    • index 생성, 동기화, 백업 등 사용자가 볼 수 없는, 백그라운드의 작업에 할당합니다. 에너지 효율에 중점을 둡니다.
  • 6️⃣ Unspecified

    • Unspecified는 QoS의 정보가 없음을 나타내며, 시스템이 QoS를 추론해야 한다.

attributes

  • DispatchQueue의 속성을 정해준다.

  • 기본값: Serial 값으로 생성된다. (main)

  • .concurrent: 다중 스레드로 DispatchQueue를 생성한다. (global())

  • .initiallyInActive: 작업을 큐에 담아놓을 뿐, active()를 호출하기 전까지는 작업을 처리하지 않도록 할 수 있다. DispatchWorkItem을 사용

    • 예시
    import Foundation
    
    let yellow = DispatchWorkItem {
        for _ in 1...5 {
            print("😀😀😀😀😀")
            sleep(1)
        }
    }
    
    let myDispatch = DispatchQueue(label: "Odong", attributes: .initiallyInactive)
    
    myDispatch.async(execute: yellow) // 코드 블록 호출 안됨.
    myDispatch.activate()

autoreleaseFrequency

  • DispatchQueue가 자동으로 객체를 해제하는 빈도의 값을 결정하는 파라미터
  • 즉 객체를 autorealease해주는 빈도이며 기본값은 inherit입니다.
    • inherit: target과 같은 빈도.
    • workItem: workItem이 실행될 때마다 객체들을 해제.
    • never: autorelease를 하지 않는다.

target

  • 코드 블록을 실행할 큐를 target으로 설정

DispatchGroup

  • 비동기적으로 처리되는 작업들을 그룹으로 묶어, 그룹 단위로 작업 상태를 추적할 수 있는 기능

  • 이를 통해 async들을 묶어서 그룹의 작업이 끝나는 시점을 추적하여 어떠한 동작을 수행시킬 수 있다. 묶어줄 async 작업들이 꼭 같은 큐, 스레드에 있지 않더라도 묶어줄 수 있습니다.

  • 반드시 async에서만 사용이 가능하다.

  • 사용하는 방법은 다음과 같다

    • group 파라미터로 지정하거나
    • 코드의 앞 뒤로 .enter(), .leave() 메서드를 호출하는 방법이다.
    let group = DispatchGroup()
    
    // enter, leave를 사용하지 않는 경우
    DispatchQueue.main.async(group: group) {}
    DispatchQueue.global().async(group: group) {}
    
    // enter, leave를 사용하는 경우
    group.enter()
    DispatchQueue.main.async {} // group에 포함되게 된다
    DispatchQueue.global().async {} // group에 포함되게 된다
    group.leave()
  • notify를 이용해 작업이 끝나고 원하는 동작을 수행시킬 수 있다.

    group.notify(queue: .main) {
        print("모든 작업이 끝났습니다.")
    }
  • wait을 통해 DispatchGroup의 수행이 끝나기를 기다리도록 할 수 있다.

    • timeout 파라미터를 입력해서 기다릴 시간을 지정시킬 수 있다. 기다린 시간이 지나면 더 이상 기다리지 않고 바로 다음 작업을 수행한다.

출처: 야곰닷넷 동시성 프로그래밍 강좌

profile
학생입니다

0개의 댓글