에서 kotlinx.coroutines
라이브러리 당신이 중 하나를 사용하여 새 코 루틴을 시작할 수 있습니다 launch
(과 join
) 또는 async
(로를 await
). 그들 사이의 차이점은 무엇입니까?
답변
-
launch
코 루틴 을 발사하고 잊는 데 사용됩니다 . 새 스레드를 시작하는 것과 같습니다. 내부 코드launch
가 예외로 종료 되면 일반적으로 백엔드 JVM 애플리케이션의 stderr에 인쇄되어 Android 애플리케이션과 충돌하는 스레드에서 포착되지 않은 예외로 처리 됩니다.join
시작된 코 루틴의 완료를 기다리는 데 사용되며 예외를 전파하지 않습니다. 그러나 추락 된 자식 코 루틴은 해당 예외와 함께 부모를 취소합니다. -
async
일부 결과를 계산하는 코 루틴 을 시작하는 데 사용됩니다 . 그 결과의 인스턴스로 표현된다Deferred
당신은 있어야 사용await
그것을.async
코드 내부의 포착되지 않은 예외 는 결과 내부에 저장되며Deferred
다른 곳에서는 전달되지 않으며 처리되지 않으면 자동으로 삭제됩니다. async로 시작한 코 루틴을 잊지 마십시오 .
답변
이 가이드 https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md 가 유용하다는 것을 알았습니다 . 필수 부분을 인용하겠습니다
? 코 루틴
본질적으로 코 루틴은 가벼운 실입니다.
따라서 코 루틴을 스레드를 매우 효율적인 방식으로 관리하는 것으로 생각할 수 있습니다.
? 발사
fun main(args: Array<String>) {
launch { // launch new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
따라서 launch
백그라운드 스레드를 시작하고 무언가를 수행하고 즉시 토큰을로 반환합니다 Job
. 이 스레드가 완료 될 때까지 차단 join
하기 Job
위해 이것을 호출 할 수 있습니다launch
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch { // launch new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
}
? 비동기
개념적으로 비동기는 시작과 같습니다. 그것은 다른 모든 코 루틴과 동시에 작동하는 가벼운 실인 별도의 코 루틴을 시작합니다. 차이점은 launch가 Job을 반환하고 결과 값을 전달하지 않는 반면 async는 Deferred를 반환한다는 것입니다. 이는 나중에 결과를 제공하겠다는 약속을 나타내는 경량 비 차단 미래입니다.
따라서 async
백그라운드 스레드를 시작하고 무언가를 수행하고 즉시 토큰을로 반환합니다 Deferred
.
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
지연된 값에 .await ()을 사용하여 최종 결과를 얻을 수 있지만 지연은 작업이기도하므로 필요한 경우 취소 할 수 있습니다.
그래서 Deferred
사실이다 Job
. https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html을 참조 하십시오.
interface Deferred<out T> : Job (source)
? 비동기는 기본적으로 열망합니다.
CoroutineStart.LAZY 값을 가진 선택적 시작 매개 변수를 사용하여 비 동기화하는 게으름 옵션이 있습니다. 일부 대기자가 결과를 필요로하거나 시작 함수가 호출 된 경우에만 코 루틴을 시작합니다.
답변
launch
및 async
새로운 코 루틴을 시작하는 데 사용됩니다. 그러나 그들은 다른 방식으로 실행합니다.
차이점을 매우 쉽게 이해하는 데 도움이되는 매우 기본적인 예를 보여 드리고자합니다
- 시작하다
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnCount.setOnClickListener {
pgBar.visibility = View.VISIBLE
CoroutineScope(Dispatchers.Main).launch {
val currentMillis = System.currentTimeMillis()
val retVal1 = downloadTask1()
val retVal2 = downloadTask2()
val retVal3 = downloadTask3()
Toast.makeText(applicationContext, "All tasks downloaded! ${retVal1}, ${retVal2}, ${retVal3} in ${(System.currentTimeMillis() - currentMillis)/1000} seconds", Toast.LENGTH_LONG).show();
pgBar.visibility = View.GONE
}
}
// Task 1 will take 5 seconds to complete download
private suspend fun downloadTask1() : String {
kotlinx.coroutines.delay(5000);
return "Complete";
}
// Task 1 will take 8 seconds to complete download
private suspend fun downloadTask2() : Int {
kotlinx.coroutines.delay(8000);
return 100;
}
// Task 1 will take 5 seconds to complete download
private suspend fun downloadTask3() : Float {
kotlinx.coroutines.delay(5000);
return 4.0f;
}
}
이 예제에서 내 코드는 btnCount
버튼 을 클릭하면 3 개의 데이터를 다운로드 하고 pgBar
모든 다운로드가 완료 될 때까지 진행률 표시 줄을 표시합니다. 3 개 있습니다 suspend
기능 downloadTask1()
, downloadTask2()
및 downloadTask3()
다운로드 데이터. 시뮬레이션하기 위해 delay()
이러한 기능을 사용 했습니다. 이 기능을 기다립니다 5 seconds
, 8 seconds
그리고 5 seconds
각각.
launch
이러한 일시 중단 기능을 시작하는 데 사용한 것처럼 순차적으로 하나씩launch
실행됩니다 . 이는 완료 후 시작되고 완료된 후에 만 시작됨을 의미합니다 .downloadTask2()
downloadTask1()
downloadTask3()
downloadTask2()
출력 스크린 샷에서와 같이 Toast
3 회 다운로드를 모두 완료하는 데 걸리는 총 실행 시간은 5 초 + 8 초 + 5 초 = 18 초 입니다.launch
- 비동기
우리가 보았 듯이 3 가지 작업 모두에서 launch
실행 sequentially
됩니다. 모든 작업을 완료하는 데 시간이 걸렸습니다 18 seconds
.
이러한 작업이 독립적이고 다른 작업의 계산 결과가 필요하지 않은 경우 실행할 수 있습니다 concurrently
. 동시에 시작하여 백그라운드에서 동시에 실행됩니다. 이 작업을 수행 할 수 있습니다 async
.
async
suspend 함수가 반환하는 데이터 유형 인 Deffered<T>
유형 의 인스턴스를 T
반환합니다. 예를 들어
downloadTask1()
반환Deferred<String>
문자열로하는 함수의 반환 형식입니다downloadTask2()
반환Deferred<Int>
(int)로하는 기능의 반환 형식입니다downloadTask3()
반환Deferred<Float>
플로트로하는 함수의 반환 형식입니다
async
유형 의 return 객체를 사용하여 유형 Deferred<T>
의 반환 값을 얻을 수 T
있습니다. 그것은 await()
전화로 할 수 있습니다 . 예를 들어 아래 코드를 확인하십시오.
btnCount.setOnClickListener {
pgBar.visibility = View.VISIBLE
CoroutineScope(Dispatchers.Main).launch {
val currentMillis = System.currentTimeMillis()
val retVal1 = async(Dispatchers.IO) { downloadTask1() }
val retVal2 = async(Dispatchers.IO) { downloadTask2() }
val retVal3 = async(Dispatchers.IO) { downloadTask3() }
Toast.makeText(applicationContext, "All tasks downloaded! ${retVal1.await()}, ${retVal2.await()}, ${retVal3.await()} in ${(System.currentTimeMillis() - currentMillis)/1000} seconds", Toast.LENGTH_LONG).show();
pgBar.visibility = View.GONE
}
이런 식으로, 우리는 3 가지 작업을 동시에 시작했습니다. 따라서 완료하는 데 걸리는 총 실행 시간 은 3 개의 작업 중 가장 큰 8 seconds
시간에 불과 downloadTask2()
합니다. 당신은 이것을 다음 스크린 샷에서 볼 수 있습니다Toast message
답변
-
코 루틴 빌더, 즉 launch 및 async는 기본적으로 CoroutineScope 유형의 리시버를 가진 람다입니다. 즉, 내부 블록이 일시 중단 기능으로 컴파일되므로 둘 다 비동기 모드로 실행되며 둘 다 블록을 순차적으로 실행합니다.
-
실행과 비동기의 차이점은 두 가지 가능성을 가능하게한다는 것입니다. 실행 빌더는 작업을 리턴하지만 비동기 함수는 지연된 오브젝트를 리턴합니다. launch를 사용하면 데이터베이스에 쓰거나 파일을 저장하거나 기본적으로 부작용으로 호출 된 것을 처리하는 등 반환 된 값을 기대하지 않는 블록을 실행할 수 있습니다. 반면에 앞서 언급했듯이 Deferred를 반환하는 async는 데이터를 래핑하는 객체 인 블록의 실행에서 유용한 값을 반환하므로 주로 결과뿐만 아니라 부작용에도 사용할 수 있습니다. NB : await 함수를 사용하여 지연된 값을 제거하고 값을 얻을 수 있습니다. 그러면 값이 반환되거나 예외가 발생할 때까지 명령문의 실행이 차단됩니다!
-
코 루틴 빌더 (시작 및 비동기)는 모두 취소 가능합니다.
-
아무것도 더? : 블록 내에서 예외가 발생하면 실행으로 코 루틴이 자동으로 취소되고 예외가 전달됩니다. 반면에 비동기로 발생하면 예외가 더 이상 전파되지 않으며 반환 된 Deferred 객체 내에서 포착 / 처리되어야합니다.
-
코 루틴에 대한 자세한 내용 https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html
https://www.codementor.io/blog/kotlin-coroutines-6n53p8cbn1
답변
발사 는 직업을 반환
async 는 결과를 반환합니다 (지연된 작업).
join with launch는 작업이 완료 될 때까지 대기하는 데 사용됩니다. join ()을 호출하는 코 루틴을 일시 중단하여 현재 스레드가 다른 작업 (예 : 다른 코 루틴 실행)을 자유롭게 수행 할 수 있습니다.
async 는 일부 결과를 계산하는 데 사용됩니다. 코 루틴을 작성하고 향후 결과를 지연 구현으로 리턴합니다. 결과 지연이 취소되면 실행중인 코 루틴이 취소됩니다.
문자열 값을 반환하는 비동기 메서드를 고려하십시오. async 메소드를 await없이 사용하면 Deferred 문자열을 반환하지만 await를 사용하면 결과로 문자열을 얻습니다.
비동기와 실행의 주요 차이점 지연은 코 루틴 실행이 완료된 후 T 유형의 특정 값을 반환하지만 작업은 그렇지 않습니다.
답변
발사 / 비동기 결과 없음
- 결과가 필요 없을 때 사용
- 호출되는 코드를 차단하지 마십시오.
- 병렬로 실행
결과에 대한 비동기
- 결과를 기다려야하고 효율성을 위해 병렬로 실행할 수있는 경우
- 호출되는 코드를 차단
- 병렬로 실행