[코틀린 동시성 프로그래밍] 5장 이터레이터, 시퀀스 그리고 프로듀서 -2

Sdoubleu·2023년 1월 17일
0

코틀린 동시성

목록 보기
9/10
post-thumbnail

프로듀서

  • 시퀀스와 이터레이터에는 실행 중에 중단할 수 없다는 제한이 있음

  • 한계를 극복하려면 프로듀서를 사용해야 함

  • 프로듀서의 사상과 사용법은 일시 중단 시퀀스/이터레이터와 비슷하지만
    차이 존재

  • 프로듀서에 대한 중요한 세부 사항

  1. 프로듀서는 값이 생성된 후 일시 중단되며, 새로운 값이 요청될 때 다시 재개
    이는 일시 중단 시퀀스/이터레이터와 유사

  2. 프로듀서는 특정 CoroutineContext로 생성할 수 있음

  3. 전달되는 일시 중단 람다의 본문은 언제든지 일시 중단될 수 있음

  4. 어느 시점에서든 일시 중단할 수 있으므로 프로듀서의 값을 일시 중단 연산에서만 수신할 수 있음

  5. 채널을 사용해 작동하므로 데이터를 스트림처럼 생각할 수 있음
    요소를 수신하면 스트림에서 요소가 제거

🛠️ 채널에 대해 .. 6장에 나온다고 한다 ..

프로듀서 만들기

  • 프로듀서를 만들려면 코루틴 빌더 producer() 를 호출해야 함
    -> ReceiveChannel<E> 를 리턴
    -> 프로듀서는 채널 위에 구축되므로 프로듀서의 요소를 산출하기 위해
    send(E) 함수를 사용
    val producer = GlobalScope.produce { 
        send(1)
    }

launch()async()와 같은 방식으로 CoroutineContext를 지정할 수 있다.
    val context = newSingleThreadContext("myThread")
  
    val producer2 = GlobalScope.produce(context){
        send(1)
    }

이터레이터/시퀀스와 마찬가지로 타입을 지정할 수 있으며,
배출된 요소가 이를 준수하는 작동한다.

    val producer3: ReceiveChannel<Any> = GlobalScope.produce(context) {
        send(5)
        send("a")
    }

프로듀서와 상호작용

  • 시퀀스/이터레이터를 사용해 수행되는 방식을 혼합한 것

프로듀서의 모든 요소 읽기

  • 프로듀서의 모든 요소를 살펴보기 위해 consumerEach() 함수 사용
val context = newSingleThreadContext("myThread")

val producer = GlobalScope.produce(context) {
	for(i in 0..9) send(i)
}
producer.consumeEach { println(it) }

단일 요소 받기

  • 프로듀서로부터 단일 요소를 읽으려면 다음과 같이 receive() 함수를 사용
val producer: ReceiveChannel<Any> = GlobalScope.produce() {
    send(5)
    send("a")
}
fun main(args: Array<String>) = runBlocking {
    println(producer.receive())
    println(producer.receive())
}

요소 그룹 가져오기

  • take() 의 매개변수로 요소의 개수를 제공해서 값을 읽을 수 있음
producer.take(3).consumeEach {
	println(it)
}

-> 왜 안됨?

ReceiveChannel<E> 의 take()ReceiveChannel<E> 를 반환
take() 는 중간 연산 이므로 종단 연산이 발생할 때 세 요소의 실제 값이 계산
종단 연산은 consumerEach()

사용 가능한 요소보다 더 많은 요소 사용하기

  • 이터레이터/시퀀스의 경우 가능한 것보다 많은 요소를 검색하면
    -> NoSuchElementException 유형의 예외가 발생
// 10개 요소까지 배출할 수 있는 채널을 고려하면 코드는 실패 X
producer.take(12).consumeEach {
	println(it)
}
// consumeEach는 얼마나 많은 요소를 가져오려 했는지 상관없이
// 더 이상 요소가 없으면 중지

val element = producer.receive()
// 다른 요소에 별개의 receive()를 추가하면 앱이 중단

프로듀서 인 액션

profile
개발자희망자

0개의 댓글