回答:
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
ように、これらは順次(1つずつ)実行されます。これは、が完了したdownloadTask2()
後downloadTask1()
に開始し、が完了したdownloadTask3()
後downloadTask2()
にのみ開始することを意味します。
出力スクリーンショットのようにToast
、3つのダウンロードすべてを完了するための合計実行時間は、5秒+ 8秒+ 5秒= 18秒になります。launch
- 非同期
見てきたように、3つのタスクすべてlaunch
が実行さsequentially
れます。すべてのタスクを完了する時間はでした18 seconds
。
これらのタスクが独立していて、他のタスクの計算結果を必要としない場合は、実行することができますconcurrently
。それらは同時に開始し、バックグラウンドで同時に実行されます。これはで行うことができますasync
。
async
Deffered<T>
タイプのインスタンスをT
返します。ここで、中断関数が返すデータのタイプです。例えば、
downloadTask1()
返すDeferred<String>
文字列は、関数の戻り値の型であるとして、downloadTask2()
戻ってくるDeferred<Int>
のInt関数の戻り値の型であるとして、downloadTask3()
戻ってくるDeferred<Float>
フロートは、関数の戻り値の型であるとして、async
typeのreturnオブジェクトを使用して、type 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
、同時実行の
launch
、async
新しいコルーチンを開始します。子供のいない単一のコルーチンと3人の子供を持つ単一のコルーチンを比較しています。async
呼び出しのそれぞれを置き換えることができlaunch
、同時実行性に関しては何も変更されません。
両方のコルーチンビルダー、つまりlaunchとasyncは基本的に、タイプがCoroutineScopeのレシーバーを持つラムダです。つまり、それらの内部ブロックは中断関数としてコンパイルされます。したがって、どちらも非同期モードで実行され、どちらもブロックを順次実行します。
起動と非同期の違いは、2つの異なる可能性を可能にすることです。Launch Builderはジョブを返しますが、非同期関数はDeferredオブジェクトを返します。launchを使用して、ブロックからの戻り値を期待しないブロックを実行できます。つまり、データベースへの書き込み、ファイルの保存、または基本的にその副作用のために呼び出されたものの処理です。一方、前に述べたようにDeferredを返すasyncは、データをラップするオブジェクトであるブロックの実行から有用な値を返すため、主に結果に使用できますが、副作用にも使用できます。注:関数awaitを使用して遅延オブジェクトを取り除き、その値を取得できます。これにより、値が返されるか、例外がスローされるまでステートメントの実行がブロックされます。
コルーチンビルダー(起動と非同期)はどちらもキャンセルできます。
何か他にありますか:はい、起動時にブロック内で例外がスローされた場合、コルーチンは自動的にキャンセルされ、例外が配信されます。一方、それが非同期で発生した場合、例外はそれ以上伝播されず、返されたDeferredオブジェクト内でキャッチ/処理する必要があります。
コルーチンの詳細 https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html https://www.codementor.io/blog/kotlin-coroutines-6n53p8cbn1
打ち上げは仕事を返します
asyncは結果を返します(据え置きジョブ)
ジョイン付きの起動は、ジョブが完了するまで待機するために使用されます。それは、join()を呼び出すコルーチンを一時停止し、その間、現在のスレッドが他の作業(別のコルーチンの実行など)を行えるようにします。
asyncは、いくつかの結果を計算するために使用されます。コルーチンを作成し、Deferredの実装として将来の結果を返します。結果の遅延オブジェクトがキャンセルされると、実行中のコルーチンがキャンセルされます。
文字列値を返す非同期メソッドを考えます。asyncメソッドがawaitなしで使用された場合、Deferred文字列を返しますが、awaitが使用された場合、結果として文字列を取得します
非同期と起動の主な違い。Deferredは、コルーチンの実行が終了した後にT型の特定の値を返しますが、Jobは返しません。
起動/非同期結果なし
結果の非同期