[iOS] Operation

Judy·2022년 12월 13일
0

iOS

목록 보기
22/28

Operation

CGD를 객체 지향적으로 재탄생시킨 high-level의 API


GCD와 차이점

GCD에서 Task라고 불렀던 코드블록을 캡슐화, 객체화(타입화) 한 것

동시성 프로그래밍과 관련된 작업들이 Operation 객체로서 만들어지게 됨
Operation 객체 : 수행할 작업이 캡슐화된 객체
이런 객체 들은 각각 실행시킬 수도 있고, GCD처럼 OperationQueue에 넣어서 실행 및 관리를 해줄 수 있음

장점

  • 재사용에 용이
  • 타입 간의 관계를 만들어줄 수 있다
  • 다양한 프로퍼티를 활용할 수 있다
  • 스케쥴링에 용이

사용방법

let  order1 = BlockOperation {
	print("1번 작업중")
}

let  order2 = BlockOperation {
	print("2번 작업중")
}

let  order3 = BlockOperation {
	print("3번 작업중")
}

let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperation = 2	// 동시에 2개의 작업 가능

operationQueue.addOperation(order1)
operationQueue.addOperation(order2)
operationQueue.addOperation(order3)

실행할 코드 블럭을 객체화하는DispatchWorkItem과 비슷하지 않나? 🤔
DispatchWorkItem보다 Operation이 먼저 나왔다는 사실!
그리고 OperationQueue의 기능에 있어서도 차이가 있다.

Operation 생성하기

Operation은 추상 클래스로 이를 상속받는 타입을 사용해야 합니다. 커스텀 클래스를 하위 클래스로 만들어주는 방법이 있고, BlockOperation라는 하위 클래스를 사용하는 방법이 있습니다.

let operation = BlockOperation {
	// 작업 코드
}

operation.addExecutionBlock = {
	// operation이 실행된 후 실행될 코드
}

operation.completionBlock = {
	// ExecutionBlock이 실행된 후 실행될 코드
}

Operation 실행하기

1) 직접 실행하기

operation.start()
  • 권장되지 않는 방법 (동기로 실행되기 땨문에)

2) OperationQueue에 넣기

let operationQueue = OperationQueue()
operationQueue.addOperation(operation)
  • OperationQueue에 넣어주기만 하면 바로 실행됨

Operation의 상태

  • isReady : Operation이 실행할 준비를 마침
  • isExecuting :Start가 호출된 이후
  • isCancel : Operation이 취소됨
  • isFinished : Operation이 실행할 준비를 마침

Operation의 프로퍼티

var isCancelled: Bool
var isExecuting: Bool
var isFinished: Bool
var isConcurrent: Bool
var isAsynchronous: Bool
var isReady: Bool
var name: String?
  • Operation의 상태를 추적할 수 있는 다양한 프로퍼티가 존재
    => GCD와 차이점 (DispatchWorkItemisCancelled는 존재)
  • name도 확인할 수 있음
  • name을 제외하고는 모두 읽기 전용


isAsynchronous

  • 기본값은 false
  • 비동기로 동작하고자 한다면 Operation을 커스텀해서 사용
  • start()로 실행한 경우
    => 동기 - 현재 스레드에서 작업을 처리
    => 비동기 - 새로운 스레드를 만들어서 작업을 처리
  • OperationQueue에 넣어서 실행한 경우
    => isAsynchronous와 상관없이 새로운 스레드를 만들어 작업

Operation 메서드

Cancel

  • isCancelledtrue로 변경해줌
  • 실행중인 작업을 강제로 취소시키진 않음
  • 취소하는 동작을 하고 싶다면 isCancelled를 추적해서 작업을 관리하면 됨


waitUntilFinished

  • Operation이 동작하고 있는 스레드에서 해당 Operation이 끝날 때까지 기다리는 메서드
  • Deadlock에 빠지지 않게 조심

Dependency

  • Operation 인스턴스들 사이에 종속적인 관계를 만들어 실행의 순서를 관리
  • 기본적으로는 OperationQueue에 넣은 순서대로 실행
operation1.addDependency(operation2)
  • operation2의 실행이 끝나야 operation1이 실행될 수 있음
  • 서로 다른 OperationQueue에 있어도 유효
  • removeDependency(_:)로 삭제도 가능
  • 서로가 서로를 기다리는 Deadlock을 조심해야 함

OperationQueue

DispatchQueue vs OperationQueue

DispatchQueue

  • sync/async, main/global 중요

OperationQueue

  • sync/async 정보는 Operation이 가지고 스레드 관리는 OperationQueue가
  • 모든 Operation에 대해 새로운 스레드를 만들어서 작업을 처리
  • 큐에 추가하면 실행될 때까지 큐에 남아있게 되고 직접 삭제 불가
  • 모든 operation이 끝날 때까지 Queue는 유지
  • 완료되지 않은 작업을 중단시키면 Queue와 Operation이 메모리에 남아 누수가 발생할 수 있음

인스턴스 생성

main, current

  • main: 메인 스레드에서 동작하는 OperationQueue를 반환
  • current: 현재 작업을 시작한 OperationQueue를 반환 (옵셔널)
let queue = OperationQueue()
let mainQueue = OperationQueue.main
let currentQueue = OperationQueue.current

프로퍼티

maxConcurrentOperationCount

  • 한 번에 수행될 수 있는 작업의 최대 개수
  • 별도의 설정이 없으면 기본적으로 비동기로 진행


qualityOfService

  • Operation의 Qos -> 우선순위를 지정


isSuspended

  • 대기열이 Operation 스케줄링이 진행 중인지 나타냄
  • false => 대기열의 Operation을 진행
  • true => 현재 실행 중인 Operation만 실행하고 대기열의 Operation을 진행하지 않음
  • 중단된 대기열에 새로운 작업을 추가할 순 있지만 실행되지는 않음
  • 계속 중단된 상태로 있으면 메모리 누수가 발생할 수 있음

메서드

addOperation

  • OperationQueue에 Operation을 추가하는 메서드
  • 추가되는 동시에 작업이 수행됨


cancelAllOperations

  • 대기열에 있는 모든 Operation의 cancel 메서드를 실행


waitUntilAllOperationsAreFinished

  • 현재 스레드를 차단하고 OperationQueue의 모든 Operation의 실행이 끝날 때까지 기다림
  • 현재 스레드 큐에는 작업을 추가할 수 없음 (다른 스레드는 가능)
  • DispatchGroup의 wait()과 비슷



참고 링크
야곰닷넷 - Operation

profile
iOS Developer

0개의 댓글