Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Coroutine Kyuin
Search
uzzu
December 20, 2018
Technology
2
270
Coroutine Kyuin
社内勉強会「冬休み前にKotlinのCoroutinesを吸引したい人が集う会」資料
uzzu
December 20, 2018
Tweet
Share
More Decks by uzzu
See All by uzzu
Context Receiversに思いを馳せる / Context Receivers
uzzu
0
630
StoreKitのこれまでとこれから / StoreKit 2 from 1
uzzu
5
13k
Autofill Framework
uzzu
0
100
アプリ内課金の最新事情 クライアントサイド編 / In-app Purchase in Cookpad 2019
uzzu
3
4.3k
Billing Client 2.0 acknowledgement
uzzu
0
16k
Promoting IAP対応から学ぶ外部アプリ内課金実装 / Promoting IAP and others
uzzu
2
1.4k
ブログ作り直した / My blog @ Othlo Tech
uzzu
0
130
新規アプリ開発を支えるユーザ・決済基盤
uzzu
2
2.7k
kotlin-mpp-library-tips
uzzu
1
6.2k
Other Decks in Technology
See All in Technology
抽象化をするということ - 具体と抽象の往復を身につける / Abstraction and concretization
soudai
20
8.3k
データマネジメントのトレードオフに立ち向かう
ikkimiyazaki
6
1k
2024.02.19 W&B AIエージェントLT会 / AIエージェントが業務を代行するための計画と実行 / Algomatic 宮脇
smiyawaki0820
14
3.6k
ハッキングの世界に迫る~攻撃者の思考で考えるセキュリティ~
nomizone
13
5.2k
Nekko Cloud、 これまでとこれから ~学生サークルが作る、 小さなクラウド
logica0419
2
980
表現を育てる
kiyou77
1
220
OpenID BizDay#17 KYC WG活動報告(法人) / 20250219-BizDay17-KYC-legalidentity
oidfj
0
250
トラシューアニマルになろう ~開発者だからこそできる、安定したサービス作りの秘訣~
jacopen
2
2k
Tech Blogを書きやすい環境づくり
lycorptech_jp
PRO
1
240
急成長する企業で作った、エンジニアが輝ける制度/ 20250214 Rinto Ikenoue
shift_evolve
3
1.3k
次世代KYC活動報告 / 20250219-BizDay17-KYC-nextgen
oidfj
0
260
君も受託系GISエンジニアにならないか
sudataka
2
440
Featured
See All Featured
Visualization
eitanlees
146
15k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
10
1.3k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.6k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
410
A Tale of Four Properties
chriscoyier
158
23k
Thoughts on Productivity
jonyablonski
69
4.5k
Designing Experiences People Love
moore
140
23k
Why Our Code Smells
bkeepers
PRO
336
57k
Optimising Largest Contentful Paint
csswizardry
34
3.1k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Transcript
ౙٳΈલʹ ,PUMJOͷ$PSPVUJOFTΛ ٵҾ͍ͨ͠ਓ͕ू͏ձ !V[[V
झࢫ w,PUMJOͰՌग़ͧ͢ w·ͩ$PSPVUJOFTΑ͔ͬͯ͘ͳ͍ͧ w$PSPVUJOFTରԠਓࡐʹͳΔͧ
ຊ w ,PUMJOϕʔεͰ͠·͢ w$PSPVUJOFTͱ wଞݴޠʹ͓͚ΔBTZODBXBJUͱͷҧ͍ w͍ํͬ͘͟Γ wͱΓ͜ΕϦϯΫू
$PSPVUJOFT w,PUMJO͔Βਖ਼ࣜϦϦʔε͞Εͨඇಉظϓϩάϥ ϛϯάͷҝͷػೳ ͪΖΜNVMUJQMBUGPSNରԠ wଞݴޠͰ͍͏ॴͷBTZODBXBJUؚ͕·Ε͍ͯΔ wଞݴޠͰ͍͏ॴͷDPSPVUJOF HFOFSBUPS ,PUMJOͰ4FRVFODF5
BTZODBXBJU $ class Program { static async ValueTask<int> DoSomething(int value)
{ await Task.Delay(1000); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var result = await DoSomething(100); Console.WriteLine($"Result: {result}"); } static void Main(string[] args) => MainAsync(args).Wait(); }
BTZODBXBJU $ class Program { static async ValueTask<int> DoSomething(int value)
{ await Task.Delay(1000); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var result = await DoSomething(100); Console.WriteLine($"Result: {result}"); } static void Main(string[] args) => MainAsync(args).Wait(); }
BTZODBXBJU $ class Program { static async ValueTask<int> DoSomething(int value)
{ await Task.Delay(1000); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var result = await DoSomething(100); Console.WriteLine($"Result: {result}"); } static void Main(string[] args) => MainAsync(args).Wait(); }
BTZODBXBJU &4 function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve,
milliSeconds)); } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
BTZODBXBJU &4 function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve,
milliSeconds)); } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
BTZODBXBJU &4 function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve,
milliSeconds)); } async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
BTZODBXBJU wBTZODGVODUJPOΛ࣮ͯ͠ ݺͼग़͠ଆͰBXBJU͢Δ
$PSPVUJOFT suspend fun doSomething(value: Int): Int { delay(1000) return value
* value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
$PSPVUJOFT suspend fun doSomething(value: Int): Int { delay(1000) return value
* value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
$PSPVUJOFT suspend fun doSomething(value: Int): Int { delay(1000) return value
* value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
$PSPVUJOFT wTVTQFOEGVODUJPOΛ࣮ͯ͠ ݺͼग़͠ଆͨͩݺͿ BXBJULFZXPSEͳ͠ BTZODBXBJUͳݴޠͰඇಉظͰ͋Δࣄ͕લఏ ,PUMJOͰඇಉظؔͰͳ͘தஅؔͳͷͰ ɹಉظzతzʹهड़Ͱ͖ΔΑ͏ʹͳ͍ͬͯΔ ɹଞݴޠͷΑ͏ʹಉظඇಉظΛҙࣝ͢Δඞཁ͕ͳ͍
͍ํ w%FQFOEFODJFTͷՃ w$PSPVUJOF4DPQFΛ࣮͢Δ w$PSPVUJOF4DPQFMBVODIͯ͠ Α͠ͳʹTVTQFOEGVODUJPOΛݺͼग़͢
%FQFOEFODJFTͷՃ w,PUMJOdΛೖΕΔ͚ͩͰ࣮࣭͑ͳ͍ ݴޠͱͯ͠ϨΠϠʔͳ༷ͷΈಉ͍ࠝͯ͠Δҝ wՃ͑ͯɺ1MBUGPSNʹ߹ΘͤͯϥΠϒϥϦΛՃ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1"
$PSPVUJOF4DPQFΛ࣮͢Δ wTVTQFOEGVODUJPO$PSPVUJOFͷத͋Δ͍ TVTQFOEGVODUJPO͔ΒͷΈར༻Ͱ͖Δ w$PSPVUJOF$PSPVUJOF4DPQFͷதͰͷΈ ىಈͰ͖Δ w$PSPVUJOF4DPQFͷ࣮͕ඞཁ
$PSPVUJOF4DPQFΛ࣮͢Δ suspend fun doSomething(value: Int): Int { delay(1000) return value
* value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") } ݱࡏͷ࣮ߦεϨουΛݩʹ CoroutineScopeΛ࡞ͬͯ ࣮ߦྃ·ͰͬͯΔ
$PSPVUJOF4DPQFΛ࣮͢Δ w࣮ͷલʹগ͚ͩ͠ొਓͷཧ ਂೖΓ͢ΔͱऴΘΒͳ͍ͷͰগ͚ͩ͠
࣮͢Δ্Ͱ࠷ݶͷొਓ w$PSPVUJOF$POUFYUϓϩύςΟͱͯ࣋ͭ͠ඞཁ͕͋Δ w+PCMBVODI͢Δ$PSPVUJOFͷϥΠϑαΠΫϧΛཧ w$PSPVUJOF%JTQBUDIFS࣮ߦίϯςΩετ 5ISFBEFUD wଞɺ$PSPVUJOF&YDFQUJPO)BOEMFS͍Δ ͕Ұ୴์ஔ
$PSPVUJOF4DPQFΛ࣮͢Δ class SimpleCoroutineScope(ui: CoroutineDispatcher) : CoroutineScope { // JobΛ࡞Δ(࡞Ε) private
val job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠ // JobjobϓϩύςΟͷͭ // ࣮ߦίϯςΩετίϯετϥΫλҾuiΛ༻͍Δ override val coroutineContext: CoroutineContext = job + ui }
$PSPVUJOF4DPQFΛ࣮͢Δ class SimpleCoroutineScope : CoroutineScope { // JobΛ࡞Δ(࡞Ε) private val
job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠ // JobjobϓϩύςΟͷͭ // ࣮ߦίϯςΩετmainϧʔϓΛ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.Main }
$PSPVUJOF4DPQFΛ࣮͢Δ class SimpleCoroutineScope : CoroutineScope { // JobΛ࡞Δ(࡞Ε) private val
job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠ // JobjobϓϩύςΟͷͭ // ࣮ߦίϯςΩετIO Pool(※ThreadͱݶΒͳ͍)Λ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.IO }
$PSPVUJOF4DPQFMBVODI͢Δ w جຊతͳॴͱͯ͠ MBVODI͢Δͱ$PSPVUJOF͕ى ಈ͢Δ $PSPVUJOF࣮ࡍ͍ΖΜͳॴͰىಈ͍ͯ͠Δ͚Ͳলུ wMBVODIͷલʹొਓΛʜ
ొਓ w$PSPVUJOF4DPQF͖ͬ͞࡞ͬͨͭ w$PSPVUJOF$POUFYU͖ͬ͞ϓϩύςΟʹ࣋ͨͤͨͭ w$PSPVUJOFMBVODIʹΑͬͯ࡞ΒΕΔ࣮ࡍʹಈ͍ͯΔͭ w+PC ུ %JTQBUDIFS FUDʜ͖ͬ͞આ໌ͨͭ͠ wଞɺ$PSPVUJOF4UBSU͋Δ͕Ұ୴লུ
$PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { // JobΛ࡞Δ(࡞Ε) private val
job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠ // JobjobϓϩύςΟͷͭ // ࣮ߦίϯςΩετmainϧʔϓΛ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.Main }
$PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { private val job: Job
= Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun foo() { launch { // Λjob // ࣮ߦίϯςΩετΛmainϧʔϓͱͯ͠ // CoroutineΛىಈ͠ॲཧΛ࣮ߦ͢Δ val result = doSomething() } } }
$PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { // JobΛ࡞Δ(࡞Ε) private val
job: Job = Job() // σϑΥϧτͷڍಈͱͯ͠ // JobjobϓϩύςΟͷͭ // ࣮ߦίϯςΩετIO Pool(※ThreadͱݶΒͳ͍)Λ༻͍Δ override val coroutineContext: CoroutineContext = job + Dispatchers.IO }
$PSPVUJOF4DPQFMBVODI͢Δ class SimpleCoroutineScope : CoroutineScope { private val job: Job
= Job() override val coroutineContext: CoroutineContext = job + Dispatchers.IO fun foo() { launch { // Λjob // ࣮ߦίϯςΩετΛIO Poolͱͯ͠ // CoroutineΛىಈ͠ॲཧΛ࣮ߦ͢Δ val result = doSomething() } } }
$PSPVUJOF4DPQFMBVODI͢Δ wิɿ͜ΕDPNQJMFFSSPS SFUVSOͰ͖ͳ͍ fun execute(): Int { launch { return
doSomething() } }
TVTQFOEGVODUJPOΛ࣮͢Δ suspend fun doSomething(value: Int): Int { delay(1000) return value
* value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") }
TVTQFOEGVODUJPOΛ࣮͢Δ suspend fun doSomething(value: Int): Int { delay(1000) return value
* value } fun main() = runBlocking { println("Start task") val result = doSomething(100) println("Result: $result") } ͜Εsuspend function
TVTQFOEGVODUJPOΛ࣮͢Δ function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve, milliSeconds));
} async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })();
TVTQFOEGVODUJPOΛ࣮͢Δ function sleep(milliSeconds) { return new Promise(resolve => setTimeout(resolve, milliSeconds));
} async function doSomething(value) { await sleep(1000); return value * value; } (async() => { console.log("Start task."); const result = await doSomething(100); console.log(`Result: ${result}`) })(); ԞͰ͜Ε૬ͷͳʹ͔Λ ࣮͢Δඞཁ͕͋Δ
TVTQFOEGVODUJPOΛ࣮͢Δ w࣮ͷલʹొਓΛʜ
TVTQFOEGVODUJPOΛ࣮͢Δ wTVTQFOE$PSPVUJOFTVTQFOEGVODUJPOΛ࣮͢Δҝͷ ɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹɹ#VJMEFSGVODUJPO w$POUJOVBUJPOTVTQFOEGVODUJPOΛ࠶։͢Δҝͷ&NJUUFSɹ wଞɺTVTQFOE $PSPVUJOFɺ $POUJOVBUJPO γϦʔζ͕͍͔ͭ͋͘Δ͚ͲҰ୴লུ
TVTQFOEGVODUJPOΛ࣮͢Δ suspend fun doSomething(value: Int): Int = suspendCoroutine { continuation
-> continuation.resume(value * value) } suspend fun doSomething(value: Int): Int = suspendCoroutine { continuation -> continuation.resumeWithException(Throwable()) }
طଘίʔυΛTVTQFOEGVO w$14 ͍ΘΏΔDBMMCBDLܗࣜ ͔ΒҠߦ͍ͨ͠߹ fun doSomethingAsync(value: Int, listener: Listener) {
if (value <= 0) { listener.onError(Throwable()) } else { listener.onSuccess(value) } } suspend fun doSomething(value: Int): Int = suspendCoroutine { doSomethingAsync(value, object : Listener { override fun onSuccess(value: Int) { it.resume(value) } override fun onError(e: Throwable) { it.resumeWithException(e) } }) }
طଘίʔυΛTVTQFOEGVO w3FBDUJWFd͔ΒҠߦ͍ͨ͠߹ม༻ϥΠϒϥϦΛ͏ ҎԼ3Y+BWBͷྫ fun doSomethingSingle(value: Int): Single<Int> = Single.just(value
* value) suspend fun doSomething(value: Int): Int = doSomethingSingle(value).await() implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.0.1"
ྫ֎र͍͍ͨ launch { try { val result = doSomething() }
catch (e: Throwable) { // } } launch { runCatching { doSomething() } // Result<T>͕ฦ٫͞ΕΔ .onSuccess { value -> } .onFailure { throwable -> } } ,PUMJO͔ΒՃͷSVO$BUDIJOHਪ
࣮ߦίϯςΩετม͍͑ͨ class SimpleCoroutineScope : CoroutineScope { private val job: Job
= Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun execute() { launch { // Main runCatching { // Main withContext(Dispatchers.IO) { // IO doSomething() } } .onSuccess { value -> // Main } .onFailure { throwable -> // Main } } } }
Ωϟϯηϧ͍ͨ͠ $ static async ValueTask<int> DoSomething(int value, CancellationToken token) {
await Task.Delay(1000); token.ThrowIfCancellationRequested(); return value * value; } static async Task MainAsync(string[] args) { Console.WriteLine("Start task"); var cancellable = new CancellationTokenSource(); var task = DoSomething(100, cancellable.Token); cancellable.Cancel(); var result = await task; Console.WriteLine($"result: {result}"); }
Ωϟϯηϧ͍ͨ͠ &4 async function doSomething(value, token) { await sleep(1000); await
token.rejectIfCancelled(); return value * value; } (async() => { const cancellable = new Cancellable(); const finalize = () => cancellable.cancel(); process.on('exit', finalize); console.log("Start task."); doSomething(100, cancellable.token); console.log(`Result: ${result}`); process.removeListener('exit', finalize); })(); Cancellable.js https://gist.github.com/uzzu/7d6e89fafc4bcde1c6f6d82a3d164409 ˢྫ͕ѱ͍͕OPEFͰϓϩηεؒ௨৴ͭͭ͠ظλεΫ࣮ߦͯͯ͠ʜͳ࣌ͱ͔
Ωϟϯηϧ͍ͨ͠ class SimpleCoroutineScope : CoroutineScope { private val job: Job
= Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun onDestroy() { job.cancel() } }
Ωϟϯηϧ͍ͨ͠ class SimpleCoroutineScope : CoroutineScope { private val job: Job
= Job() override val coroutineContext: CoroutineContext = job + Dispatchers.Main fun onDestroy() { job.cancel() } } ࢠͷJob(Coroutine)͕શ෦cancel͞ΕΔ ݸผʹcancel͍ͨ͠έʔεʹ͍ͭͯলུ
ͱΓ͜ΕϦϯΫू w$PSPVUJOF(VJEF IUUQTHJUIVCDPN,PUMJOLPUMJOYDPSPVUJOFTCMPC NBTUFSDPSPVUJOFTHVJEFNE ຊޠ༁IUUQTHJUIVCDPNQMKQLPUMJOYDPSPVUJOFTCMPC KBQBOFTF@USBOTMBUJPODPSPVUJOFTHVJEFNE w,PUMJO$POGͰࢀՃͨ͠XPSLTIPQ IUUQTHJUIVCDPNFMJ[BSPW$PSPVUJOFT8PSLTIPQ ຊʹॳาతͳॴ͔Β"DUPS 1SPEVDFS·Ͱ͔Δ
Ұ୴͜͜·Ͱ
ଞτϐοΫฉ͖͍ͨࣄ͋Εޙ΄ͲͲ͏ͧ w "EWBODFE 3Y+BWBΛར༻࣮ͨ͠ͱͷൺֱΛͯ͠ΈΑ͏ TVTQFOEGVODUJPOΛෳΒ͍ͤͨBTZODͷར༻ํ๏ͱҙ +BWBίʔυͱͷ૬ޓӡ༻ .VUFY ଟॏݺͼग़͠ࢭIPUMBVODI IPUTVTQFOEGVODUJPO ໋໊ద
6OJU5FTUͷॻ͖ํ $PSPVUJOF4UBSU $PSPVUJOF&YDFQUJPO)BOEMFS TVTQFOE$PSPVUJOF$POUJOVBUJPOγϦʔζ ଞඈౕͨ͠ $IBOOFM "DUPS 1SPEVDFS w %FFQ%JWJOH KPC EJTQBUDIFS ʜ ͬͯԿ ͲΜͳίʔυʹͳΔͷόΠτίʔυݟͳ͕Β $PSPVUJOFͷதͲ͏ͳͬͯΜͷιʔείʔυಡΈͳ͕Β NVMUJQMBUGPSNؔ࿈