BT

あなたのご意見でInfoQが変わる! InfoQアンケートに答える

Kotlinの新しい非同期処理 - QCon SFでのRoman Elizarov氏の講演より

| 作者: Amit K Gupta フォローする 6 人のフォロワー , 翻訳者 h_yoshida フォローする 1 人のフォロワー 投稿日 2018年1月5日. 推定読書時間: 4 分 |

原文(投稿日:2017/11/20)へのリンク

JetBrainsでKotlinライブラリの開発リーダを務めるRoman Elizarov氏がQCon Sun Franciscoで、“Fresh Async with Kotlin”と題した講演を行なった。講演の中で氏は、JavaやC#、JavaScriptなどの言語で非同期コードを記述することの難しさと、Kotlinがいかに対処しているかを実演してみせた。Kotlinで書かれた非同期コードは、Javaなどの言語で多くの開発者が書き慣れている通常の同期コードとほとんど変わらない。

従来のアプリケーションは直接的な計算や処理が中心だったが、新しいアプリケーションでは、多くがREST APIやマイクロサービスといったサービスの呼び出しを行なっている。このアーキテクチャスタイルでは、結果が戻ってくるのを待つのが一般的だ。

Image 1

上記のコードはrequestToken()サービスをコールしてtokenを待ち、取得したトークンをcreatePost()サービスに渡して生成されるpostを待った上で、最後にprocessPost()サービスをコールしてpostを表示する。

この処理を実装する簡単な方法のひとつはスレッドを使うことだ。しかしながら、上の3ステップのような単純なケースならば問題にはならないが、多数のサービスコールが関わる複雑なアプリケーションでは、スレッドに大きく依存する方法が機能しない場合がある。各スレッドがメモリとスケジューリングのオーバヘッドを持つため、最新鋭のマシンでさえ、一度に起動できるスレッドの数には制限があるからだ。

特にJavaScriptを使用したシングルスレッド環境において、スレッドの代替となるのがコールバックだ。しかしコードバックを使用したコードは、以下の例に示すような、“コールバック地獄(callback hell)”と呼ばれる過剰なネストを起こしやすい。

Image 2

このようなコードのネストの問題は、複雑なコードではさらに悪化する — コールバックでネストしたコードは本質的に読み難く、デバッグが難しいのだ。

近年では、コールバック地獄の問題に対処する優れた代用策として、Future/Promise/Rxが知られるようになった。これらはすべて、同じアイデアを異なる言語で実装したものだ。

Future/Promiseを使用して記述されたコードは、コールバック地獄よりも読みやすく、理解も容易だ。このアプローチには例外処理機構も組み込まれているため、コードのデバッグも簡単になる。

しかしながら、Future/Promiesを使った場合にも、以前として潜在的な問題がある。例えば、Futureコンテナオブジェクトで複数のコンビネータメソッドを処理する場合だ。先程のコードでは、.thenCompose.thenAcceptという2つのコンビネータを使用する。コンビネータは他の言語では違う名称を持つ場合もある。また、開発者は、コードブランチやループのためのコンビネータも意識しなくてならない。

Kotlinのコルーチンは、開発者がFuture/Promiseで直面する問題の緩和を目標とする。コルーチンでは、同期コードの記述で使用するような、自然なシグネチャでコードを書くことができる。コルーチン定義の先頭では、非同期オペレーションを示すためにsuspendというキーワードを使用する。

Image 4

このアプローチの欠点は、どのサービス呼び出しが非同期なのかを知るのが難しいことだ。例えば上記のコードでは、requestToken()createPost()コールが非同期であることを指定する方法がない。この問題にはIDEが、ガター内のサスペンドポイントマーカを示すことで貢献してくれる。

コルーチンを使うことで、一般的なループや例外処理、forEachletapplyrepeatfiltermapuseなどの一般的な高次関数を記述できるようになった。独自の高次関数も、同期コーディングで使用される通常のコーディングスタイルで作成可能だ。

内部的には、suspendキーワードが指定されていると、KotlinコンパイラがJVMバイトコードのレベルで、関数呼び出しに暗黙のContinuationパラメータを追加する。このContinuationパラメータは、基本的にはコールバックである。

Image 5

コード内にサスペンドポイントが見つかると、Kotlinはそれをステートマシンにコンパイルして、サスペンドをそのステートマシンに保存する。

Image 6

非同期プログラミングをサポートする目的でKotlinに用意されているすべてのコルーチンを知るには、Kotlinのコルーチンライブラリを調べるとよいだろう。これらライブラリは現在も開発中であるため、現時点では試験的(experimental)とされているが、この中にはCompleteableFuture、RxJava、Reactive Streamsといった他の非同期プログラミングアプローチとの統合や、AndroidやJavaFXといったシングルスレッドUIフレームワークとKotlinとの統合を実現するフックも含まれている。

 
 

この記事を評価

採用ステージ
スタイル
 
 

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

あなたの意見をお聞かせください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする
コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

ディスカッション
BT