본문 바로가기
728x90

공부/코틀린코루틴:딥다이브(마르친 모스카와)15

30장 - 모범 사례 async 코루틴 빌더 뒤에 await 를 호출하지 마세요 async 로 비동기 작업을 정의한 뒤, 아무것도 하지 않은 채 연산이 완료되는 걸 기다리는건 아무 의미가 없습니다. // 이렇게 구현하지 마세요. suspend fun getUser(): User = coroutineScope { val user = async { repo.getUser() }.await() user.toUser() } // 이렇게 구현하세요. suspend fun getUser(): User { val user = repo.getUser() return user.toUser() } withContext(EmptyCoroutineContext) 대신 coroutineScope 를 사용하세요 withContext 와 corouti.. 2024. 3. 16.
29장 - 코루틴을 시작하는 것과 중단 함 숮 어떤 것이 나을까? 여러 개의 동시성 작업을 수행해야 하는 경우 사용할 수 있는 함수는 두 종류가 있다. 코루틴 스코프 객체에서 실행되는 일반 함수 중단 함수 class CoroutineTest29 { @Test fun `29_1 test`() { main_29_1() /* send: Notificationabc(message=Message #4) send: Notificationabc(message=Message #3) send: Notificationabc(message=Message #0) send: Notificationabc(message=Message #2) send: Notificationabc(message=Message #1) NotificationsSender를 통해 모든 알림이 전송되었습니다. */ } .. 2024. 3. 16.
18장 - 핫 데이터 소스와 콜드 데이터 소스 채널만으로 부족하다라는 것을 깨닫음. 채널은 값을 핫 스트림으로 가지지만, 콜드 스트림이 필여힐 때가 있음 핫 데이터, 콜드 데이터 차이를 이해하는 것이 소프트웨어적인 측면에서 상당히 유용하다 할 수 있다. List, Set과 같은 컬렉션은 핫 이며, Sequence 와 Stream 은 콜드입니다 Channel 은 핫이지만, Flow 와 (Observable, Sigle 과 같은)RxJava 스트림은 콜드입니다. 핫 VS 콜드 핫 데이터 스트림은 열정적이라 데이터를 소비하는 것과 무관하게 원소를 생성하지만 핫 데이터 스트림의 빌더와 연산은 즉각 실행됩니다. 콜드 데이터 스트림은 게을러서 요청이 있을 때만 작업을 수행하며 아무것도 저장하지 않습니다. 콜드 데이터 스트림에서는 원소가 필요할 때까지 실행되지 .. 2024. 3. 10.
16장 - 채널 채널은 송신자와 수신자의 수에 제한이 없으며, 채널을 통해 전송된 모든 값은 단 한 번만 받을 수 있습니다. SendChannel 은 원소를 보내거나(또는 더하거나) 채널을 닫는 용도로 사용됩니다. ReceiveChannel 은 원소를 받을 때(또는 꺼낼때) 사용됩니다. 채널의 진입점을 제한하기 위해 ReceiveChannel 이나, SendChannel 중 하나만 노출시키는 것도 가능합니다. 원소를 보내고 받는 함수가 중단 함수인 것은 필수적인 특징입니다. receive: 호출했는데 채널에 원소가 없다면 코루틴은 원소가 들어올 때 까지 중단됩니다. send: 채널의 용량이 다 찼을 때 중단됩니다. *중단 함수가 아닌 함수로 보내거나 받아야 한다면 trySend, tryReceive 를 사용할 수 있다... 2024. 3. 2.
14장 - 공유 상태로 인한 문제 위 예제에서는 방어적 복사로 toList 를 사용했습니다. downloaded 로 반환된 객체를 읽을 때와 변경 가능한 리스트에 원소를 추가할 때 발생할 수 있는 충돌을 피하기 위함입니다.users 를 읽기만 가능한 리스트(List) 와 읽고 쓰기가 가능한 프로퍼티(var) 로 선언할 수도 있습니다.방어적 복사를 하지 않아도 되고 downloaded 함수를 보호할 필요도 없지만 컬렉션에 원소를 추가하는 작업의 효율이 떨어지게 됩니다.개인적으로 두번째 방법을 선호하지만, 실제 현업의 많은 프로젝트에서 변경 가능한 컬렉션을 사용하고 있으므로 첫 번째 방법을 예로 들었습니다. users.toList()를 통해 생성된 복사본은 List 타입입니다. 이 복사본은 기본적으로 변경할 수 없습니다. 즉, 복사본은 수정.. 2024. 3. 1.
13장 - 코루틴 스코프 만들기 코루틴 스코프 객체를 만드는 가장 쉬운 방법은 CoroutineScope 팩토리 함수를 사용하는 것입니다 fun main() { // CoroutineScope 팩토리 함수를 사용하여 코루틴 스코프 생성 val scope = CoroutineScope(Dispatchers.Default) // 코루틴 스코프 내에서 코루틴 실행 scope.launch { // 비동기적으로 작업 수행 delay(1000L) println("CoroutineScope Example") } // 메인 스레드를 1.5초 동안 차단하여 코루틴이 완료되기를 기다림 Thread.sleep(1500L) } Ktor 에서 모든 핸들러는 기본적으로 중단 함수이다.따로 스코프를 만들 필요는 거의 없습니다 https://tech.kakaopa.. 2024. 2. 26.
12장 - 디스패처 코틀린 코루틴 라이브러리가 제공하는 중요한 기능은 코루틴이 실행되어야 할 스레드를 결정할 수 있다는 것 디스패처를 이용해 이러한 기능을 사용할 수 있다. 기본 디스패처 디스패처를 설정하지 않으면 기본적으로 설정되는 디스패처는 CPU 집약적인 연산을 수행하도록 설계된 DIpatchers.Default 입니다. 코드가 실행되는 컴퓨터의 CPI 개수와 동일한 수(최소 두 개 이상)의 스레드 풀을 가지고 있습니다. runBlocking은 주로 테스트나 메인 함수와 같은 블로킹 환경에서 코루틴 코드를 실행하기 위해 사용됩니다. runBlocking을 호출하면 호출한 스레드를 블로킹합니다. 즉, runBlocking 블록 내의 모든 코루틴 작업이 완료될 때까지 현재 스레드가 대기 상태가 됩니다. runBlockin.. 2024. 2. 20.
9장 - 취소 코틀린 코루틴에서 아주 중요한 기능 중 하나는 바로 취소(cancellation) 이다. 기본적인 취소 Job 인터페이스는 취소하게 하는 cancel 메서드를 가지고 있습니다. cancel 메서드를 호출하면 다음과 같은 효과를 가져올 수 있다. 호출한 코루틴은 첫 번째 중단점에서 잡을 끝냅니다. 잡이 자식을 가지고 있다면, 그들 또한 취소됩니다.하지만 부모는 영향을 받지 않는다. 잡이 취소되면, 취소된 잡은 새로운 코루틴의 부모로 사용될 수 없다. 취소된 Job 은 Cancelling 상태가 되었다가 Cancelled 상태로 바뀝니다. @Test fun `98페이지`() { runBlocking { val job = launch { repeat(1_000) { i -> delay(200) println(.. 2024. 2. 5.
8장 - 잡과 자식 코루틴 기다리기 자식은 부모로부터 컨텍스트를 상속받습니다. 부모는 모든 자식이 작업을 마칠 때까지 기다립니다. 부모 코투린이 취소되면 자식 코루틴도 취소됩니다. 자식 코루틴에서 에러가 발생하면, 부모 코루틴 또한 에러로 소멸합니다. Job 이란? 시작된 코루틴에 대한 핸들로 사용된다. launch 코루틴 빌더는 Job 객체를 반환하고, 이 객체를 사용하여 코루틴이 완료될 때까지 대기하거나 코루틴의 상태를 관리할 수 있다. 코루틴 빌더는 부모의 잡을 기초로 자신들의 잡을 생성한다. 모든 코루틴 빌더는 자신만의 잡을 생성합니다. 대부분의 코루틴 빌더는 잡을 반환하므로 어느 곳에서든 사용할 수 있습니다. launch 의 명시적 반환 타입이 Job 이라는 사실을 통해 확인할 수 있습니다. Job 은 코루틴이 상속하지 않는 유일.. 2024. 1. 29.
728x90