ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코루틴(Coroutine) 기초
    프로그래밍/Kotlin 2024. 1. 29. 16:22

    코루틴을 사용하기 전 의존성을 추가해야한다.

    dendendcies {
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3")
        testImplementation(kotlin("test))
    }

     

     

    runBlocking

    • 코루틴을 생성하는 코루틴 빌더.
    • runBlocking으로 감싼 코드는 코루틴 내부의 코드가 수행이 끝날 때까지 스레드가 블록킹된다.
    fun main() {
    
    	runBlocking {
        	println("hello")
            println(Thread.currentThread().name)
        }
        println("world")
        println(Thread.currentThread().name)
    }
    // Hello
    // main @coroutine#1
    // world
    // main
    
    
    // 둘다 main thread 이지만 코루틴 블럭에서 실행된 코드는 스레드에 coroutine 수식어가 붙어있다.
    // 이를 확인하려면 - d 를 누른 후 kotlinx coroutines debug 옵션을 넣자.
    // runBlocking 실행이 끝나야 다음 코드가 읽힌다.
    // 잘 쓰이지 않는다.

     

     

     

    launch

    • 스레드 차단 없이 새 코루틴을 시작하고 결과로 잡이라 하는 결과를 반환하는 코루틴 빌더
    • 실행에 대한 흐름 조절 가능
    • 단, 비동기 처리에 대한 결과를 가져오는것은 불가
    fun main() = runBlocking<Unit> {
    
    	launch {
        	delay(500) // 코루틴 라이브러리에서 정의된 일시중단. 스레드를 블록킹하지 않음.
            // Thread.sleep(500) 스레드를 블록킹 함
            println("world")
        }
        
        println("hello")
    }
    
    // hello
    // world
    
    fun main() = runBlocking<Unit> {
    
    	val job1: Job = launch {
    		val elapsedTime = measureTimeMillis {
            	delay(150)
            }
            println("async task-1 $elapsedTime ms")
        }
        job1.cancel()
        
    	val job2: Job = launch {
    		val elapsedTime = measureTimeMillis {
            	delay(100)
            }
            println("async task-2 $elapsedTime ms")
        }
        
        val job3: Job = launch(start=CoroutineStart.LAZY) {
    	    val elapsedTime = measureTimeMillis {
            	delay(100)
        	}
            println("async task-3 $elapsedTime ms")
        }
        
        println("start task-3")
        job3.start()
    }

     

     

     

    async builder 

    • 비동기 작업을 통해서 결과를 만들어 낼 때 사용
    • 비동기 처리를 할 때 async 함수를 사용하고 결과를 받아올 때는 await 을 사용해주면 된다.
    • 병렬 처리도 가능하다
    • 반환 타입은 Deffered<T> 로 되어 있으며, Deffered 내부에는 결과를 받아올 수 있는 await을 제공하고 있다.
    fun sum(a: Intm b:Int) = a + b
    
    fun main() = runBlocking<Unit> {
    
    	val result1: Deffered<Int> = async {
        	delay(100)
            sum(1,3)
        }
        
        println("result1 : ${result1.await()}")
        
        val result2 = async {
            delay(100)
            sum(2,5)
        }
        
        println("result2 : ${result2.await()}")
    }

     

     

     

    suspend

    • 코루틴의 핵심 요소로 일시 중단이 가능한 함수를 말한다.
    • suspend 함수는 일반 함수를 마음껏 호출할 수 있지만 일반 함수에선 suspend 함수를 일반적으로는 바로 호출 불가능
    • 호출을 위해 runblocking 을 사용하던지, 호출함수가 suspend 가 되어야 한다.
    • suspend 함수에서 async, launch 와 같은 코루틴 빌더를 사용하려면 coroutineScope를 사용해야 한다.
    • coroutineScope 와 runblocking 의 다른점은 coroutineScope 은 현재 스레드가 차단되지 않는다 (논블록킹)
    suspend fun main() {
    	doSomething()
    }
    
    fun printHello() = println("hello")
    
    suspend fun doSomething() = coroutineScope {
    	laynch {
        	delay(200)
            println("world")
        }
    	laynch {
            printHello()
        }
    }

     

     

     

    flow

    • 코루틴에서 리액티브 프로그래밍 스타일로 작성할 수 있도록 만들어진 API
    • suspend 함수의 경우 reactor Mono 처럼 단일 값을 비동기로 반환하지만 flow을 사용하게되면 reactor Flux 처럼 여러 개의 값을 반환할 수 있다.
    • flow 도 리액티브 스타일처럼 최종 연산자인 collect 를 호출해 줘야만 이 코드가 동작한다.
    fun main() = runBlocking<Unit> {
    	val flow = simple()
        flow.collect{ value -> println(value) } 
    }
    
    fun simpel(): Flow<Int> = flow {
    	println("flow started")
        
        for(i in 1..3) {
        	delay(100)
            emit(i) // 데이터 통지
        }
    }
Designed by Tistory.