채널은 코루틴끼리의 통신하기 위한 기본적인 방법이다.채널은 공공 도서관으로 비유할 수 있다. 하나의 책을 찾으려면, 책을 빌렸던 사람이 다시 반납해야 한다.이는 채널이 작동하는 방식과 비슷하다.채널은 송신자와 수신자의 수에 제한이 없고, 채널을 통해 전송된 모든 값은 단 한 번만 받을 수 있다. interface SendChannel { suspend fun send(element: E) fun close(): Boolean // ...}interface ReceiveChannel { suspend fun receive(): E fun cancel(cause: CancellationException? = null) // ...}interface Channel : SendC..
UnconfinedTestDispatcherfun main() { CoroutineScope(StandardTestDispatcher()).launch { print("A") delay(1) print("B") } CoroutineScope(UnconfinedTestDispatcher()).launch { print("C") delay(1) print("D") }}C테스트 디스패처는 StandardTestDispatcher 외에 UnconfinedTestDispatcher도 있다. StandardTestDispatcher는 스케줄러를 사용하기 전까지 어떤 연산도 수행하지 않는다.반면에 UnconfinedTes..
더보기class FetchUserUseCase( private val repo: UserDataRepository,) { suspend fun fetchUserData(): User = coroutineScope { val name = async { repo.getName() } val friends = async { repo.getFriends() } val profile = async { repo.getProfile() } User( name 三 name.await(), friends = friends.await(), profile = profile.await(), ) ..
class UserDownloader( private val api: NetworkService,) { private val users = mutableListOf() fun downloaded(): List = users.toList() suspend fun fetchUser(id: Int) { val newUser = api.fetchUser(id) users.add(newUser) }}시작하기 전에 위 코드를 살펴보자.이 클래스는 두 개 이상의 스레드가 동시에 사용할 경우에 대한 대비가 되어있지 않다.fetchUser()에서 users를 변경하고 있기 때문에, users는 공유 상태에 해당한다.따라서 users는 보호되어야 한다.두 개 이상의 스레..
이전 포스팅에서 코루틴 스코프를 적절하게 만드는 방법에 대해 배웠다.이번에는 스코프에 대해 배운 것들을 요약해 보고 일반적으로 사용하는 예시 상황에 대해 알아보자. CoroutineScope 팩토리 함수interface CoroutineScope { val coroutineContext: CoroutineContext}CoroutineScope는 coroutineContext를 유일한 프로퍼티로 가지고 있는 인터페이스이다. class SomeClass : CoroutineScope { override val coroutineContext: CoroutineContext = Job() fun onStart() { launch { // ... } ..
코루틴에서는 디스패처를 통해 코루틴이 실행되어야 할 스레드(또는 스레드 풀)를 결정한다.영어 사전에서 디스패처는 '사람이나 긴급 차량을 필요한 곳에 보내는 사람'이라 정의한다. 기본 디스패처디스패처를 설정하지 않으면 Dispatchers.Default가 기본적으로 설정된다.Dispatchers.Default는 프로그램이 실행되는 컴퓨터의 CPU 개수와 동일한 수(최소 두 개 이상)의 스레드 풀을 가지고 있다.이는 스레드를 효율적으로 사용한다고 가정했을 때, 이론적으로 가장 최적의 스레드 수다.따라서 Dispatchers.Default는 CPU 집약적인 연산을 수행하기에 적합하다. suspend fun main() = coroutineScope { repeat(1000) { launch..
여러 비동기 함수에서 데이터를 동시에 얻어야 하는 경우를 생각해 보자. 코루틴 스코프 함수가 소개되기 전에 사용한 방법들 suspend fun getUserProfile(): UserProfileData { val user = getUserData() // 1초 후 val notifications = getNotifications() // 1초 후 return UserProfileData( user = user, notifications = notifications, )}먼저 중단 함수에서 중단 함수를 호출하는 방법이 있다. 하지만 이런 방식은 작업이 동시에 진행되지 않는다.하나의 함수에서 데이터를 얻는 데 1초씩 걸리기 때문에 총 2초가 걸린다. susp..
코루틴은 잡히지 않은 예외가 발생했을 때 종료된다스레드도 동일한 경우에 종료되지만, 차이점이 있다.코루틴 빌더는 부모도 종료시키고, 종료된 부모는 자식들까지 모두 취소시킨다는 것이다. fun main(): Unit = runBlocking { launch { launch { delay(1000) throw Error("Some error") } launch { delay(2000) println("Will not be printed") } launch { delay(500) println("W..