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
290
Coroutine Kyuin
社内勉強会「冬休み前にKotlinのCoroutinesを吸引したい人が集う会」資料
uzzu
December 20, 2018
Tweet
Share
More Decks by uzzu
See All by uzzu
Context Receiversに思いを馳せる / Context Receivers
uzzu
0
690
StoreKitのこれまでとこれから / StoreKit 2 from 1
uzzu
5
16k
Autofill Framework
uzzu
0
120
アプリ内課金の最新事情 クライアントサイド編 / In-app Purchase in Cookpad 2019
uzzu
3
4.5k
Billing Client 2.0 acknowledgement
uzzu
0
17k
Promoting IAP対応から学ぶ外部アプリ内課金実装 / Promoting IAP and others
uzzu
2
1.5k
ブログ作り直した / My blog @ Othlo Tech
uzzu
0
160
新規アプリ開発を支えるユーザ・決済基盤
uzzu
2
2.8k
kotlin-mpp-library-tips
uzzu
1
6.3k
Other Decks in Technology
See All in Technology
Zero Data Loss Autonomous Recovery Service サービス概要
oracle4engineer
PRO
2
7.8k
20250707-AI活用の個人差を埋めるチームづくり
shnjtk
6
4.1k
[ JAWS-UG千葉支部 x 彩の国埼玉支部 ]ムダ遣い卒業!FinOpsで始めるAWSコスト最適化の第一歩
sh_fk2
2
150
20250708オープンエンドな探索と知識発見
sakana_ai
PRO
4
860
Delta airlines®️ USA Contact Numbers: Complete 2025 Support Guide
airtravelguide
0
350
CDK Toolkit Libraryにおけるテストの考え方
smt7174
1
450
AWS CDKの仕組み / how-aws-cdk-works
gotok365
10
890
Four Keysから始める信頼性の改善 - SRE NEXT 2025
ozakikota
0
210
60以上のプロダクトを持つ組織における開発者体験向上への取り組み - チームAPIとBackstageで構築する組織の可視化基盤 - / sre next 2025 Efforts to Improve Developer Experience in an Organization with Over 60 Products
vtryo
3
980
事例で学ぶ!B2B SaaSにおけるSREの実践例/SRE for B2B SaaS: A Real-World Case Study
bitkey
1
340
United™️ Airlines®️ Customer®️ USA Contact Numbers: Complete 2025 Support Guide
flyunitedguide
0
780
Contributing to Rails? Start with the Gems You Already Use
yahonda
2
120
Featured
See All Featured
Building a Modern Day E-commerce SEO Strategy
aleyda
42
7.4k
We Have a Design System, Now What?
morganepeng
53
7.7k
Building Adaptive Systems
keathley
43
2.7k
Into the Great Unknown - MozCon
thekraken
40
1.9k
RailsConf 2023
tenderlove
30
1.1k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
How to train your dragon (web standard)
notwaldorf
96
6.1k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
980
Facilitating Awesome Meetings
lara
54
6.5k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
7
330
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ؔ࿈