読者です 読者をやめる 読者になる 読者になる

フレームワークは非同期処理をどう解決するか

ここで扱うのはネットワーク間の非同期通信ではなく、
プログラミングでの非同期処理である。

非同期処理とは

一つの処理を待たずに違う処理を行う処理のこと。
詳しい定義はわからない。

非同期処理が特によく使われる場面

時間のかかる処理はGUIのスレッドでは行えない
(処理している間GUIを固めてしまうことになるから)
よって非同期な処理が必要となる。

  • サーバー

クライアントからのリクエストを同時に多数処理する必要があるとき。
リクエストひとつひとつにプロセスを立ち上げるのは重すぎる。


この二つは並行処理の規模などがまったく違うが、どちらも
非同期処理を頻繁に使用するため、GUI、サーバーで用いられるフレームワークには
これを実現する仕組みが備わっていることが多い。

フレームワークはどのような仕組みで非同期処理を実現しているか

・マルチスレッド
GUIプログラムなど

Androidの例

public class AsyncTest1 extends Activity 
    implements OnClickListener {
  
    Handler guiThreadHandler;
    ...  

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        guiThreadHandler = new Handler();
        ...
    }
    ...
    
    public void setTextAsync(final String text){
      guiThreadHandler.post(new Runnable(){
        @Override
        public void run() {
          view.setText(text);
        }      
      });
    }
  }

via http://android.keicode.com/basics/async-update.php

AndroidではGUIのスレッドとアプリケーションの業務本体は別のスレッドで動いているため
業務コードから直接view.setText(text)を呼べない。
ここでは非同期にUIを動かすためにGUIのイベントキューにメッセージをポストしている。

・イベントループ
node.js
(大抵のGUIプログラムはイベントループだが非同期処理は
マルチスレッドで実現している場合が多い。
node.jsはシングルスレッドながら非同期IOで並行処理を実現している)

var server = http.createServer( function (request, response) {
 response.writeHead(200, {'Content-Type': 'text/plain'}); response.write('Hello World!!\n');
 response.end(); 
} ).listen(8124);

via http://www.atmarkit.co.jp/fwcr/rensai2/nodejs01/01.html

コールバックを登録しておき、イベントが起こった場合に呼び出す。
node.jsの場合I/O処理が終わるのを待たずに複数のイベントを処理することができる。


・コルーチン(軽量スレッド)
NeverBlockなど
コルーチンはいったん処理を中断した後、続きから処理を再開できる
これを擬似スレッドとして使い非同期で処理を行う

3つの方式を挙げたが、それぞれにメリットデメリットがあり、
特に大量のリクエストを処理する必要のあるサーバーにおいては
どの方式が最適、と一概には言えない。

各方式の欠点
  • マルチスレッド

スレッドが増えすぎると重くなる。
この問題は特にサーバー処理で問題となる。
また複数のスレッドにまたがるI/O処理を記述するのが難しい。

  • イベントループ

処理一つにつきコールバックを書く必要があるためコードが複雑になりやすい。
ただ工夫次第でどうにかできる場合もある、らしい
参考:東京Node学園#1「非同期プログラミングの改善」のエッセンス

  • コルーチン

デフォルトでサポートしている言語が少ない。
フレームワークも少ない。
実際に並行に実行しているわけではないので計算速度はあまり出ない。




LuaとかRubyとか、コルーチンをサポートしてる言語で非同期処理のうまい書き方とか作れないのかな?