
Simon Wirtzã¯åœŒã®ããã°ã§ãKotlinã«é¢ããå€ãã®èå³æ·±ãæçš¿ãæçš¿ããŠããŸãã
ãã®ãã¡ã®äžã€ã®ç¿»èš³ããèŠãããŸãã
玹ä»ãšåæ©
æ°æ¥åã«ãã€ãã¿ãŒã§è¿°ã¹ãããã«ãç§ã¯ã³ãŒãªã³ã®ã³ã«ãŒãã³ã詳ãã調ã¹ãã€ããã§ããã ããããæ®å¿µãªãããäºæ³ãããæéãããããŸããã ã»ãšãã©ã®å Žåãããã¯ãç¹ã«ã«ãŒãã³ã®æŠå¿µã«ç²ŸéããŠããªãå Žåãã³ã«ãŒãã³ãéåžžã«èšå€§ãªãããã¯ã§ãããšããäºå®ã«ãããã®ã§ãã ãããã«ãããç§ã¯ããªããšç§ã®æèŠãå
±æããããšæããŸãããããŠãç§ã¯ããªãã«åŸ¹åºçãªã¬ãã¥ãŒãããããšæããŸãã
JetBrains ããã°ã§è¿°ã¹ãããŠããããã«ãã³ã«ãŒãã³ã¯ééããªãã倧ããªæ©èœãã®1ã€ã§ãã
è² è·ãããããšãããã¯ããã®ãæªãããšã GOãã»ãŒãã¹ãŠã®å Žæã§ãµã³ãã«ãšããŠäœ¿çšãããŠããããšãäžçããŸããŸãéåæã«ãªããéç¥åŠçã«åºã¥ããŠããããšãããã£ãŠããŸãã å€ãã®èšèªïŒ2012幎ã®CïŒä»¥é ïŒã¯ã async/await
ãªã©ã®æ§æèŠçŽ ã䜿çšããŠãããã«éåæããã°ã©ãã³ã°ããµããŒãããŸãã Kotlinã§ã¯ããã®ãããªæ§é ã¯ã©ã€ãã©ãªã§å®£èšã§ããéåæã¯ããŒã¯ãŒãã§ã¯ãªããåçŽãªé¢æ°ã«ãªããšæ³å®ããŠããŸããã ãã®èšèšã«ããã future/promises
ã callback-passing
ãªã©ãããŸããŸãªéåæAPIãå®è£
ã§ããŸãã é
延ãžã§ãã¬ãŒã¿ãŒïŒ yield
ïŒããã³ãã®ä»ã®æ©èœãå®è£
ããããã«å¿
èŠãªãã®ããã¹ãŠãããŸãã
ã€ãŸãããã«ãã¹ã¬ããããã°ã©ãã³ã°ãç°¡åã«å®è£
ããããã®ã³ã«ãŒãã³ãå°å
¥ãããŠããŸãã 確ãã«ããªãã®å€ãã¯ã Java ããã®Threadã¯ã©ã¹ãããã³ãã«ãã¹ã¬ããããã°ã©ãã³ã°ã®ã¯ã©ã¹ãæ±ã£ãŠããŸãã ç§èªèº«ã圌ããšå€ãã®ä»äºãããŠããŠããã圌ãã®æ±ºå®ã®æç床ã確信ããŠããŸãã
Javaãã«ãã¹ã¬ãããšKotlinã³ã«ãŒãã³
ããã§ãJavaã®ã¹ã¬ãããšãã«ãã¹ã¬ããã§åé¡ãçºçããå Žåã¯ã Javaåæå®è¡æ§ã®ç·Žç¿åž³ããå§ãããŸã ã
ãã¡ããããšã³ãžãã¢ãªã³ã°ã®èŠ³ç¹ããã Javaããã®å®è£
ã¯é©åã«èšèšãããŠããŸãããæ¥åžžã®äœæ¥ã§äœ¿çšããããšã¯é£ãããéåžžã«åé·ã§ãã ããã«ããã³ããããã³ã°ããã°ã©ãã³ã°çšã®Javaå®è£
ã¯å€ããããŸããã å€ãã®å Žåãã¹ã¬ãããéå§ãããšãã«ããããã¯ã³ãŒãïŒããã¯ãæåŸ
ãªã©ïŒã«ããã«ã¢ã¯ã»ã¹ããããšãå®å
šã«å¿ãããšããäºå®ã«æ°ä»ãããšãã§ããŸãã代æ¿ã®éããããã³ã°ã¢ãããŒã㯠ãæ¥åžžã®äœæ¥ã§ã¯äœ¿ãã«ãããééããç¯ããããã§ãã
äžæ¹ãã³ã«ãŒãã³ã¯åçŽãªã·ãŒã±ã³ã·ã£ã«ã³ãŒãã®ããã«èŠããã©ã€ãã©ãªå
ã®ãã¹ãŠã®è€éããé ããŸãã åæã«ãããã¯ãªãã§éåæã³ãŒããå®è¡ããæ©èœãæäŸããŸããããã«ãããããŸããŸãªã¢ããªã±ãŒã·ã§ã³ã«å€§ããªãã£ã³ã¹ãçãŸããŸãã ã¹ã¬ããããããã¯ãã代ããã«ãèšç®ãäžæãããŸãã JetBrainsã¯ãã³ã«ãŒãã³ãJavaã§ç¥ã£ãŠããã¹ã¬ããã§ã¯ãªããã軜éã¹ã¬ããããšããŠèª¬æããŠããŸã ã ã³ã«ãŒãã³ã¯éåžžã«å®äŸ¡ã«äœæã§ãããããŒãšæ¯èŒãããªãŒããŒãããã¯æ¯èŒã§ããŸããã åŸã§èŠãããã«ãã³ã«ãŒãã³ã¯ã©ã€ãã©ãªã®å¶åŸ¡äžã§ã¹ã¬ããã§å®è¡ãããŸãã å¥ã®éèŠãªéãã¯å¶éã§ãã ã¹ã¬ããã®æ°ã¯ãå®éã«ã¯ãã€ãã£ãã¹ã¬ããã«å¯Ÿå¿ããŠãããããå¶éãããŠããŸãã äžæ¹ãã³ã«ãŒãã³ã®äœæã¯äºå®äžç¡æã§ãããæ°ååã®ã³ã«ãŒãã³ãç°¡åã«èµ·åã§ããŸãã
ãã«ãã¹ã¬ããã¹ã¿ã€ã«
ç°ãªãèšèªã§ã¯ã callback
ïŒJavaScriptïŒã future/promise
ïŒJavaãJavaScriptïŒã async/await
ã¢ãããŒãïŒCïŒïŒãªã©ã«åºã¥ããŠããã«ãã¹ã¬ããããã°ã©ãã³ã°ãžã®ããŸããŸãªã¢ãããŒããèŠã€ããããšãã§ããŸãã ãããã¯ãã¹ãŠãããã°ã©ãã³ã°ã¹ã¿ã€ã«ã課ããªããšããäºå®ã«ãããã³ã«ãŒãã³ã䜿çšããŠå®è£
ã§ããŸãã ããã©ããããã©ã®ã¹ã¿ã€ã«ãæ¢ã«å®è£
ãããŠãããããããã®å©ããåããŠå®è£
ããããšãã§ããŸãã
å©ç¹ã®1ã€ãšããŠã callback
ããŒã¹ã®ã¢ãããŒããšæ¯èŒããŠãã³ã«ãŒãã³ã䜿çšãããšãéåæã³ãŒããå®è£
ã§ããŸããããã¯ãã·ãŒã±ã³ã·ã£ã«ã³ãŒãã®ããã«èŠããŸãã ãŸããã³ã«ãŒãã³ã¯è€æ°ã®ã¹ã¬ããã§å®è¡ã§ããŸãããã³ãŒãã®äžè²«æ§ã¯ç¶æããããããç解ãããããªããŸãã
ã³ã«ãã³ã®ã³ã³ã»ãã
ããã¯ããã³ã«ãŒãã³ãã®æŠå¿µãæ°ãããšããããšã§ã¯ãããŸããã ãŠã£ãããã£ã¢ã®èšäºã«ãããšãååèªäœã¯1958幎ã«ãã§ã«ç¥ãããŠããŸããã CïŒ ã Go ã Python ã Rubyãªã©ãå€ãã®ææ°ã®ããã°ã©ãã³ã°èšèªããã€ãã£ããµããŒããæäŸããŸãã Kotlinãå«ãã³ã«ãã³ã®å®è£
ã¯ãã³ã³ãã¥ãŒã¿ãŒããã°ã©ã ã®å¶åŸ¡ç¶æ
ã®æœè±¡çãªè¡šçŸã§ãããããããã ç¶ç¶ ãã«åºã¥ããŠããããšããããããŸãã ããããã©ã®ããã«æ©èœãããïŒã³ã«ãŒãã³ã®å®è£
ïŒã«æ»ããŸãã
ã¹ã¿ãŒãã åºæ¬
kotlinlang.orgã«ã¯ ãã³ã«ãŒãã³ã䜿çšããããã«ãããžã§ã¯ããã»ããã¢ããããæ¹æ³ã説æããå
æ¬çãªè³æããããŸãã åã®ãªã³ã¯ã®è³æã詳ããèŠããã GitHubã®ãªããžããªããã³ãŒããããŒã¹ãšããŠãã ããã
ã³ã«ãã³æå
ãã§ã«è¿°ã¹ãããã«ãã³ã«ãŒãã³ã©ã€ãã©ãªã¯ãç解ããããé«ã¬ãã«ã®APIãæäŸããããã«éå§ã§ããããã«ããŸãã åŠç¿ããå¯äžã®ä¿®é£Ÿåã¯äžæã§ãã ã¡ãœããã®è¿œå 修食åãšããŠäœ¿çšããŠãããããå²ã蟌ã¿å¯èœãšããŠããŒã¯ããŸãã
å°ãåŸã APIããã®ããã€ãã®ç°¡åãªäŸãèŠãŠã¿ãŸãããããä»ã®ãšããã¯ããŸãã¯ã suspend
æ©èœãšã¯äœãã詳ããèŠãŠã¿ãŸãããã
å²ã蟌ã¿å¯èœãªæ©èœ
ã³ã«ãŒãã³ã¯ãæ©èœãäžæãããå¯èœæ§ãããããšã瀺ãããã«äœ¿çšãããsuspend
ããŒã¯ãŒãã«åºã¥ããŠããŸãã ã€ãŸãããã®ãããªé¢æ°ã®åŒã³åºãã¯ãã€ã§ãäžæã§ããŸãã ãã®ãããªé¢æ°ã¯corutinããã®ã¿åŒã³åºãããšãã§ããcorutinã«ã¯å°ãªããšã1ã€ã®å®è¡é¢æ°ãå¿
èŠã§ãã
suspend fun myMethod(p: String): Boolean {
äžèšã®äŸãããããããã«ãå²ã蟌ã¿é¢æ°ã¯è¿œå ã®ä¿®é£Ÿåãæã€éåžžã®é¢æ°ã®ããã«èŠããŸãã ãã®ãããªé¢æ°ã¯ã³ã«ãŒãã³ããããåŒã³åºããªãããšã«æ³šæããŠãã ãããããããªããšãã³ã³ãã€ã«ãšã©ãŒãçºçããŸãã
ã³ã«ãŒãã³ã¯ãéåžžã®é¢æ°ã®ã·ãŒã±ã³ã¹ããŸãã¯å®è¡åŸã«äœ¿çšå¯èœãªãªãã·ã§ã³ã®çµæãæã€å²ã蟌ã¿é¢æ°ã®ããããã§ãã
äŸã«ç§»ããŸãããã
äœãšãäœãšãäœãšãããŠãç¹å®ã®äŸã«ç§»ããŸãããã åºæ¬ããå§ããŸãããïŒ
fun main(args: Array<String>) = runBlocking {
ãã®äŸã§ã¯ã2ã€ã®é¢æ°ïŒ1ïŒ runBlocking
ãšïŒ2ïŒ launch
ãã³ã«ãŒãã³ãã«ããŒã®äœ¿çšäŸã§ãã å€æ°ã®ç°ãªããã«ããããããããããããŸããŸãªç®çã®ã³ã«ãŒãã³ãäœæããŸãïŒ launch
ïŒäœæããŠå¿ããïŒã async
ïŒ promise
è¿ãïŒã runBlocking
ïŒãããŒããããã¯ããïŒãªã©ã
ïŒ2ïŒ launch
äœæãããå
éšã³ã«ãŒãã³ããã¹ãŠã®äœæ¥ãè¡ããŸãã äžæãããé¢æ°ïŒ3ïŒã®åŒã³åºãã¯ãã€ã§ãäžæã§ããçµæã¯èšç®åŸã«è¡šç€ºãããŸãã ã¡ã€ã³ã¹ã¬ããã§ã¯ãcorutinãéå§ããåŸãã³ã«ãŒãã³ãå®äºããåã«String
å€ã衚瀺ãããŸãã launchããèµ·åãããCorutinã¯ãããã«Job
è¿ãJob
ãããã¯ãå®è¡ããã£ã³ã»ã«ããããïŒ4ïŒ join()
ã䜿çšããŠèšç®ãåŸ
æ©ãããããããã«äœ¿çšã§ããŸãã ãŸãã join()
åŒã³åºãã¯äžæãããå¯èœæ§ãããããã runBlocking
ããã䜿çšãããå¥ã®ã³ã«ãŒãã³ã«ã©ããããå¿
èŠããããŸãã ãã®ãã«ããŒïŒ1ïŒã¯ãå²ã蟌ã¿ã®ã¹ã¿ã€ã«ã§èšè¿°ãããã³ãŒããéåžžã®ãããã¯åœ¢åŒã§åŒã³åºãããæ©äŒãæäŸããããã«ç¹å¥ã«äœæãããŸããïŒ APIããã®æ³šæïŒã join
ïŒ4ïŒãåé€join
ãšãã³ã«ãŒãã³ãçµæã®å€ã衚瀺ããåã«ããã°ã©ã ãçµäºããŸãã
ãŠãµã®ã®ç©Žããã£ãšæ·±ãèŠãŸããã
ããçŸå®ã«è¿ãäŸãèããŠã¿ãŸãããã ã¢ããªã±ãŒã·ã§ã³ã§ã¡ãŒã«ãéä¿¡ããå¿
èŠããããšæ³åããŠãã ããã åä¿¡è
ã®èŠæ±ãšã¡ãã»ãŒãžããã¹ãã®çæã«ã¯ããªãã®æéãããããŸãã äž¡æ¹ã®ããã»ã¹ã¯ç¬ç«ããŠããããããããã䞊è¡ããŠå®è¡ã§ããŸãã
suspend fun sendEmail(r: String, msg: String): Boolean { //(6) delay(2000) println("Sent '$msg' to $r") return true } suspend fun getReceiverAddressFromDatabase(): String { //(4) delay(1000) return "coroutine@kotlin.org" } suspend fun sendEmailSuspending(): Boolean { val msg = async(CommonPool) { //(3) delay(500) "The message content" } val recipient = async(CommonPool) { //(5) getReceiverAddressFromDatabase() } println("Waiting for email data") val sendStatus = async(CommonPool) { sendEmail(recipient.await(), msg.await()) //(7) } return sendStatus.await() //(8) } fun main(args: Array<String>) = runBlocking(CommonPool) { //(1) val job = launch(CommonPool) { sendEmailSuspending() //(2) println("Email sent successfully.") } job.join() //(9) println("Finished") }
äœæè
ã®ã³ãŒãã¯ãããã«åçŽåã§ããŸã
sendEmailSuspendingããã³mainã®ã³ãŒã suspend fun sendEmailSuspending(): Boolean { val msg = async(CommonPool) { delay(500) "The message content" } val recipient = async(CommonPool) { getReceiverAddressFromDatabase() } println("Waiting for email data") return sendEmail(recipient.await(), msg.await()) } fun main(args: Array<String>) = runBlocking(CommonPool) { sendEmailSuspending() println("Email sent successfully.") println("Finished") }
æåã«ãåã®äŸã§èŠãããã«ãïŒ1ïŒ runBlocking
å
ã®launch
ãã«ããŒã䜿çšãããããïŒ9ïŒã³ã«ãŒãã³ãå®äºããã®ãåŸ
ã€ããšãã§ããŸãã ïŒ2ïŒã§ã¯ãå²ã蟌ã¿é¢æ°sendEmailSuspending
ãåŒã³åºããŸãã ãã®ã¡ãœããå
ã§ã¯ã2ã€ã®äžŠåã¿ã¹ã¯ã䜿çšããŸããïŒ3ïŒã¡ãã»ãŒãžããã¹ããååŸããïŒ4ïŒ getReceiverAddressFromDatabase
ãåŒã³åºããŠã¢ãã¬ã¹ãååŸããŸãã äž¡æ¹ã®ã¿ã¹ã¯ã¯ã async
ã䜿çšããŠäžŠåã³ã«ãŒãã³ã§å®è¡ãããŸãã ãŸããé
延åŒã³åºãããããã¯ãããŠããªãããšã«æ³šæãã䟡å€ããããŸã;ã³ã«ãŒãã³ã®å®è¡ãäžæããããã«äœ¿çšãããŸãã
éåæãã«ããŒ
ãã®ãã«ããŒã¯ãã³ã³ã»ãããæ¬åœã«ã·ã³ãã«ã§ãã ä»ã®èšèªã§ã¯ã圌ã¯promiseãè¿ããŸããããã¯å³å¯ã«èšãã°ã Kotlinã§ã¯ Deferred
åãšããŠè¡šãããŸãã promise
ã future
ã deferred
ã delay
ãªã©ã®ãããã®ãšã³ãã£ãã£ã¯ãã¹ãŠé垞亀æå¯èœã§ãããåããã®ã®èª¬æã§ãã èšç®ã®çµæãè¿ãããšããçŽæããããã€ã§ãåŸ
æ©ã§ããéåæãªããžã§ã¯ãã
ïŒ7ïŒã§ã Kotlinããã®Deferred
ãªããžã§ã¯ãã®ãåŸ
æ©ãéšåãæ¢ã«èŠãŠããŸãããããã§ã¯ãäž¡æ¹ã®ã¡ãœãããåŸ
æ©ããçµæã§å²ã蟌ã¿é¢æ°ãåŒã³åºãããŸããã await()
ã¡ãœããã¯ã Deferredãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ã§åŒã³åºããããã®åŒã³åºãã¯çµæãå©çšå¯èœã«ãªããŸã§äžæãããŸãã sendEmail
åŒã³åºããéåæãã«ããŒã§ã©ããããããããå®è¡ãåŸ
æ©ã§ããŸãã
èŠéãããã®ïŒCoroutineContext
äžèšã®äŸã®éèŠãªéšåã¯ã CoroutineContext
ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã§ãããã«ããŒé¢æ°ã«æž¡ãããæåã®ãã©ã¡ãŒã¿ãŒã§ãã ãã®ã³ã³ããã¹ãã¯ãã³ã«ãŒãã³ã«æž¡ããã®ã§ãããçŸåšã®Job
ãžã®ã¢ã¯ã»ã¹ãæäŸãããã®ã§ãã
çŸåšã®ã³ã³ããã¹ãã䜿çšããŠå
éšã³ã«ãŒãã³ãéå§ã§ããŸãããã®çµæãåJob
ã¯å€éšã³ã«ãŒãã³ã®åå«ã«ãªããŸãã ããã«ããã芪Job
ãžã®1åã®åŒã³åºãã§ã³ã«ãŒãã³éå±€å
šäœãåãæ¶ãããšãã§ããŸãã
CoroutineContext
ã¯ã CoroutineContext
ããŸããŸãªã¿ã€ãã®Element
ãå«ãŸããŠããŸãã
äžèšã®ãã¹ãŠã®äŸã§ã¯ã CommonPool
䜿çšãdispatcher
ãããã¯ãŸãã«dispatcher
ã§ãã 圌ã¯ããã¬ãŒã ã¯ãŒã¯ã®å¶åŸ¡äžã§ã¹ã¬ããããŒã«ã§ã³ã«ãŒãã³ãå®è¡ãããããšãä¿èšŒãã責任ããããŸãã å¥ã®æ¹æ³ãšããŠãéå®ãããã¹ããªãŒã ããŸãã¯ç¹å¥ã«äœæãããã¹ããªãŒã ã䜿çšããããç¬èªã®ããŒã«ã䜿çšã§ããŸãã ã³ã³ããã¹ãã¯ã+æŒç®åã䜿çšããŠç°¡åã«çµåã§ããŸãã
launch(CommonPool + CoroutineName("mycoroutine")){...}
äžè¬çãªå¯å€ç¶æ
ããªãã¯ããããããã«ã€ããŠãã§ã«èããŠããŸããïŒãã¡ãããã³ã«ãŒãã³ã¯ããèŠããŸãããã©ã®ããã«åæããã©ã®ããã«ç°ãªãã³ã«ãŒãã³éã§ããŒã¿ã亀æããŸããïŒ
ããŠãããã¯ãŸãã«ç§ãæè¿å°ãã質åã§ãããããã¯ã¹ã¬ããããŒã«ã䜿çšããã»ãšãã©ã®ã³ã«ãŒãã³ã«ãšã£ãŠåŠ¥åœãªè³ªåã§ãã åæã«ã¯ãã¹ã¬ããã»ãŒããªããŒã¿æ§é ã1ã€ã®ã¹ã¬ããã§ã®å®è¡å¶éãããã¯ã®äœ¿çšãªã©ãããŸããŸãªææ³ã䜿çšã§ããŸãïŒè©³çŽ°ã«ã€ããŠã¯ã Mutex
ãMutex
ïŒã
äžè¬çãªãã¿ãŒã³ã«å ããŠã Kotlinã³ã«ãŒãã³ã¯ãéä¿¡ã«ãã亀æãã¹ã¿ã€ã«ã®äœ¿çšãæšå¥šããŸãïŒ QAãåç
§ïŒã
ç¹ã«ã俳åªã¯ã³ãã¥ãã±ãŒã·ã§ã³ã«é©ããŠããŸãã ããããã¡ãã»ãŒãžãéåä¿¡ã§ããã³ã«ãŒãã³ã§äœ¿çšã§ããŸãã äŸãèŠãŠã¿ãŸãããïŒ
俳åª
sealed class CounterMsg { object IncCounter : CounterMsg() // one-way message to increment counter class GetCounter(val response: SendChannel<Int>) : CounterMsg() // a request with channel for reply. } fun counterActor() = actor<CounterMsg>(CommonPool) { //(1) var counter = 0 //(9) actor state, not shared for (msg in channel) { // handle incoming messages when (msg) { is CounterMsg.IncCounter -> counter++ //(4) is CounterMsg.GetCounter -> msg.response.send(counter) //(3) } } } suspend fun getCurrentCount(counter: ActorJob<CounterMsg>): Int { //(8) val response = Channel<Int>() //(2) counter.send(CounterMsg.GetCounter(response)) val receive = response.receive() println("Counter = $receive") return receive } fun main(args: Array<String>) = runBlocking<Unit> { val counter = counterActor() launch(CommonPool) { //(5) while(getCurrentCount(counter) < 100){ delay(100) println("sending IncCounter message") counter.send(CounterMsg.IncCounter) //(7) } } launch(CommonPool) { //(6) while ( getCurrentCount(counter) < 100) { delay(200) } }.join() counter.close() // shutdown the actor }
äžèšã®äŸã§ã¯ã Actor
ã䜿çšãActor
ãããã¯ãããèªäœãã³ã«ãŒãã³ã§ãããä»»æã®ã³ã³ããã¹ãã§äœ¿çšã§ããŸãã ã¢ã¯ã¿ãŒã«ã¯ã counter
å«ãŸããŠããã¢ããªã±ãŒã·ã§ã³ã®çŸåšã®ç¶æ
ãå«ãŸããŠããŸãã ããã§ãŸãå¥ã®èå³æ·±ãæ©èœïŒ2ïŒ Channel
äŒããŸã
ãã£ã³ãã«
ãã£ãã«ã¯ãå€ã®ã¹ããªãŒã ã亀æããæ©èœãæäŸããŸããããã¯ãããã¯ãªãã§Javaã§BlockingQueue
ïŒãããã¥ãŒãµãŒ/ã³ã³ã·ã¥ãŒããŒãã¿ãŒã³ãå®è£
ïŒã䜿çšããæ¹æ³ã«éåžžã«äŒŒãŠããŸãã ããã«ã send
ãšreceive
ã¯å²ã蟌ã¿å¯èœãªæ©èœã§ããã FIFOæŠç¥ãå®è£
ãããã£ãã«ãä»ããŠã¡ãã»ãŒãžãéåä¿¡ããããã«äœ¿çšãããŸãã
ããã©ã«ãã§ã¯ãã¢ã¯ã¿ãŒã«ã¯ãã®ãããªãã£ãã«ãå«ãŸããŠãããä»ã®ã³ã«ãŒãã³ã§äœ¿çšããŠã¡ãã»ãŒãžãéä¿¡ã§ããŸãã äžèšã®äŸã§ã¯ãã¢ã¯ã¿ãŒã¯èªèº«ã®ãã£ã³ãã«ããã®ã¡ãã»ãŒãžãç¹°ãè¿ãåŠçãïŒããã§ã¯å²ã蟌ã¿åŒã³åºãfor
åäœããŸãïŒãã¿ã€ãã«å¿ããŠåŠçããŸãã GetCounter
ããSendChannel
ç¬ç«ããå€ãéä¿¡ãã圢åŒã§ã
ã¡ãœããïŒ5ïŒ main
ã®æåã®ã³ã«ãŒãã³ã¯äŸ¿å®äžã®ãã®ã§ãããã«ãŠã³ã¿ãŒå€ã100æªæºã«ãªããŸã§ã¡ãã»ãŒãžïŒ7ïŒ IncCounter
ãã¢ã¯ã¿ãŒã«éä¿¡ããŸãIncCounter
çªç®ïŒ6ïŒã¯ã«ãŠã³ã¿ãŒå€ã100æªæºã«ãªããŸã§åŸ
æ©ããŸãã ïŒ8ïŒ getCurrentCounter
ãããã«GetCounter
ã¡ãã»ãŒãžãGetCounter
ããå¿çã§receive
ãåŸ
æ©ããŠããéã«äžæãGetCounter
ãŸãã
ã芧ã®ãšãããå·å
šäœãç¹å®ã®ã¢ã¯ã¿ãŒã«éé¢ãããŠããŸãã ããã«ãããäžè¬çãªå¯å€ç¶æ
ã®åé¡ã解決ãããŸãã
ãã®ä»ã®æ©èœãšäŸ
ã³ã«ãŒãã³ãããæ·±ãæãäžããŠäœæ¥ãããå Žåã¯ã Kotlinã®ããã¥ã¡ã³ãããã詳现ã«èªãã§ãç¹ã«çŽ æŽãããã¬ã€ããèŠãããšããå§ãããŸã ã
ä»çµã¿-Corutinã®å®è£
æçš¿ãéè² è·ã«ããªãããã«ã詳现ã«æ·±ãå
¥ããããªãããã«ããŸãã ããã«ãä»åŸæ°é±éã®ãã¡ã«ããã€ãã³ãŒãçæã®äŸãšãšãã«ããã詳现ãªå®è£
æ
å ±ãå«ãç¶ç·šãæžãäºå®ã§ãã ãã®ãããããã§ã¯ãæã§ãç°¡åãªèª¬æã«éå®ããŸãã
ã³ã«ãŒãã³ã¯ã JVMã®æ©èœã«ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®æ©èœã«ãåºã¥ããŠããŸããã 代ããã«ãã³ã«ãŒãã³ããã³å²ã蟌ã¿å¯èœé¢æ°ã¯ãã³ã³ãã€ã©ãŒã«ãã£ãŠãç¶æ
ãç¶æããªããå²ã蟌ã¿ãã€ã³ã¿ãŒã»ããããå²ã蟌ã¿å¯èœé¢æ°ã«éä¿¡ã§ããç¶æ
ãã·ã³ã«å€æãããŸãã ããã¯ãã¹ãŠã Continuation
ãããã§å¯èœã§ããContinuationã¯ãã³ã³ãã€ã©ãŒã«ãã£ãŠãè¿œå ã®æé»ãã©ã¡ãŒã¿ãŒã®åœ¢åŒã§ãäžæãããé¢æ°ã®ååŒã³åºãã«è¿œå ãããŸãã ããã¯ãããããç¶ç¶æž¡ãã¹ã¿ã€ã«ã§ãã ãã詳现ãªèª¬æã¯ããã«ãããŸã ã
ããŒãã³ã»ãšãªã¶ããããã®ãã³ã
å°ãåãç§ã¯JetBrainsã® Roman Elizarovãšè©±ãããããšãã§ããŸãããKotlinã®ã³ã«ãŒãã³ãããŸããŸãªæ¹æ³ã§ç»å Žãããããã§ãã ãã®æ
å ±ãããªããšå
±æãããŠãã ããïŒ
QïŒæåã«åºãŠãã質åã¯ããã€ã³ã«ãŒãã³ã䜿çšããå¿
èŠããããã¹ã¬ããã䜿çšããå¿
èŠãããç¶æ³ã¯ãããŸããïŒ
AïŒã³ã«ãŒãã³ã¯ãã»ãšãã©ã®å Žåã«äœããæåŸ
ããéåæã¿ã¹ã¯ã«å¿
èŠã§ãã éäžçãªCPUã¿ã¹ã¯ã®ã¹ã¬ããã
QïŒã軜éã¹ã¬ããããšãããã¬ãŒãºã¯ãç¹ã«ã³ã«ãŒãã³ãã¹ã¬ããããŒã¹ã§ããã¹ã¬ããããŒã«ã§å®è¡ãããããšãèãããšãå°ã誀解ãæãããã«èããããšè¿°ã¹ãŸããã ã³ã«ãŒãã³ã¯ãå®è¡ãäžæãåæ¢ããããã¿ã¹ã¯ãã«äŒŒãŠããããã«æããŸãã
AïŒã軜éã¹ããªãŒã ããšãããã¬ãŒãºã¯ããªãè¡šé¢çãªãã®ã§ãã³ã«ãŒãã³ã¯å€ãã®ç¹ã§ãŠãŒã¶ãŒã®èŠ³ç¹ããèŠããšã¹ããªãŒã ã®ããã«åäœããŸã
QïŒåæã«ã€ããŠç¥ãããã®ã§ããã ã³ã«ãŒãã³ãå€ãã®ç¹ã§ãããŒã«äŒŒãŠããå Žåãç°ãªãã³ã«ãŒãã³éã§äžè¬çãªç¶æ
ã®åæãå®çŸããå¿
èŠããããŸãã
AïŒåæã«ã¯ããç¥ãããŠãããã¿ãŒã³ã䜿çšã§ããŸãããã³ã«ãã³ã䜿çšããå Žåã¯ãäžè¬çãªç¶æ
ããŸã£ããæããªãããšããå§ãããŸãã 代ããã«ãã³ã«ãŒãã³ã¯ãã³ãã¥ãã±ãŒã·ã§ã³ãéããŠäº€æã¹ã¿ã€ã«ã奚å±ããŸããã
çµè«
ã³ã«ãŒãã³ã¯ã Kotlinã«ç»å Žããéåžžã«åŒ·åãªæ©èœã§ãã ã³ã«ãŒãã³ã«åºäŒããŸã§ã Javaããã®ãã«ãã¹ã¬ããåã§ååã§ããããã«æããŸããã
Javaãšã¯å¯Ÿç
§çã«ã Kotlinã¯ãŸã£ããç°ãªãã¹ã¿ã€ã«ã®ç«¶åããã°ã©ãã³ã°ãæäŸããŸããããã¯æ¬è³ªçã«ãã³ããããã³ã°ã§ãããèšå€§ãªæ°ã®ãã€ãã£ãã¹ã¬ããã匷å¶çã«èµ·åããããšã¯ãããŸããã Javaã§ã¯ãããã倧ããªãªãŒããŒãããã§ãããšèããã«å¥ã®è¿œå ã®ã¹ã¬ãããŸãã¯æ°ããããŒã«ãäœæããããšã¯éåžžã«æ®éã§ãããããã«ããå°æ¥ã¢ããªã±ãŒã·ã§ã³ãé
ããªãå¯èœæ§ããããŸãã 代æ¿ãšããŠã®ã³ã«ãŒãã³ã¯ãããããã軜éã¹ã¬ãããã§ãããããã«ããããã€ãã£ãã¹ã¬ãããš1察1ã§çžé¢ããã deadlocks
ã starvation
ãªã©ã®åé¡ãèµ·ããã«ããããšã匷調ããŠããŸãã ãããŸã§èŠãŠããããã«ãã³ã«ãŒãã³ã䜿çšãããšããããŒã®ãããã¯ãåæã«ã€ããŠå¿é
ããå¿
èŠã¯ãããŸãããç¹ã«ãéä¿¡ã«ããéä¿¡ããé å®ããå Žåã¯ããããŒã¯ããç°¡åã«èŠããŸãã
ãŸããã³ã«ãŒãã³ã䜿çšãããšã競åããã³ãŒããäœæããããã®ããŸããŸãªã¢ãããŒãã䜿çšã§ããŸããåã¢ãããŒãã¯ãã©ã€ãã©ãªïŒ kotlinx.coroutine ïŒã«æ¢ã«å®è£
ãããŠãããããã®å©ããåããŠç°¡åã«å®è£
ã§ããŸãã
Javaéçºè
ã¯ãã¿ã¹ã¯ãã¹ã¬ããããŒã«ã«éä¿¡ãã ExecutorService
ã䜿çšããŠfuture
çµæãåŸ
ã€ããšã«æ
£ããŠããå¯èœæ§ãé«ãã§ãExecutorService
ã¯ã ExecutorService
ã async/await
ã䜿çšããŠç°¡åã«å®è£
ã§ããŸãã ã¯ããããã¯å®å
šã«åçã®ä»£æ¿åã§ã¯ãããŸããããããã§ã倧ããªæ¹åã§ãã
Javaã§ã®äžŠè¡ããã°ã©ãã³ã°ãžã®ã¢ãããŒããåå®çŸ©ããŸããããããã¹ãŠã®ãã§ãã¯äŸå€ãããŒãããããã³ã°æŠç¥ã倧éã®å®åã³ãŒãã ã³ã«ãŒãã³ã®å Žåãé¢æ°ãsuspend
åŒã³åºãã䜿çšããŠã³ãŒããé£ç¶ããŠèšè¿°ããä»ã®ã³ã«ãŒãã³ãšéä¿¡ããçµæãåŸ
æ©ããã³ã«ãŒãã³ããã£ã³ã»ã«ãããªã©ãéåžžã«æ£åžžã§ãã
èŠèŸŒã¿
ããã«ãããããããã³ã«ãŒãã³ã¯æ¬åœã«çŽ æŽããããšç¢ºä¿¡ããŠããŸãã ãã¡ãããè² è·ãé«ããã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠæ¬åœã«æçããŠãããã©ããã¯æéãçµãŠã°ããããŸãã å€åå€ãã®ããã°ã©ããŒã§ãããããã°ã©ãã³ã°ãžã®ã¢ãããŒããèããåèããã§ãããã 次ã«äœãèµ·ããããèŠãã®ã¯èå³æ·±ãã§ãã , , , JetBrains , , .
ãããïŒ . , - . .
Simon