2009-02-28 9 views

答えて

50

これは興味深い質問です。

非同期プログラミングは、主にシングルスレッド、すなわち「1つの連続実行スレッドに従う」プログラミングのパラダイムです。

あなたはjavascriptを参照しているので、ウェブブラウザの環境でその言語について話し合うことができます。 Webブラウザは各ウィンドウでJavaScriptの実行スレッドを1つ実行し、イベント(onclick = "someFunction()"など)とネットワーク接続(xmlhttprequest呼び出しなど)を処理します。

<script> 
function performRequest() { 
    xmlhttp.open("GET", "someurl", true); 
    xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
     alert(xmlhttp.responseText); 
    } 
    } 
    xmlhttp.send(sometext); 
} 
</script> 
<span onclick="performRequest()">perform request</span> 

(これは概念的なデモンストレーションのためだけの例です)。

非同期ですべてを行うために、制御スレッドには「メインループ」があります。メインループは次のようになります。

while (true) { 
    event = nextEvent(all_event_sources); 
    handler = findEventHandler(event); 
    handler(event); 
} 

これは「ビジーループ」ではありません。これは眠っているスレッドのようなもので、アクティビティの発生を待ちます。アクティビティはユーザから入力することができます(マウス移動、ボタンクリック、タイプ入力)、またはネットワークアクティビティ(サーバからの応答)が可能です。ユーザは、スパンをクリックするときに、上記の例では、

  1. は、ButtonClickedイベントが生成される

    、findEventHandler()は、spanタグ上のonclickイベントを見つけるだろうし、そのハンドラがあろうイベントで呼び出されました。

  2. xmlhttp要求が作成されると、イベントソースのall_event_sourcesリストに追加されます。
  3. performRequest()関数が返った後、mainloopは応答を待っているnextEvent()ステップで待機しています。この時点で、さらなるイベントが処理されることを「ブロックする」ことはありません。
  4. データがリモートサーバーから返され、nextEvent()がネットワークイベントを返し、イベントハンドラがonreadystatechange()メソッドであると検出され、そのメソッドが呼び出され、alert()ダイアログが起動します。

alert()はブロックダイアログです。そのダイアログが立ち上がっている間は、それ以上のイベントは処理できません。これは、WebページのJavaScriptモデルの偏心です。すぐに利用できるメソッドがあり、そのページのコンテキスト内でさらに実行をブロックします。特に、JavaScriptの程度

+0

は答えの編集を提案します "それは価値がありません" は とは違う "それは価値がありません" 私はあなたの意志だと思います。読者のための混乱を避けるために。 – MadMurf

+0

@MadMurf:私はそれも気付きました....そしてそれを修正しました。 – mpen

+0

>>非同期プログラミングは、主にシングルスレッドのプログラミングのパラダイムです。<<ここではペタントなものではありませんが、このステートメントがどのように真実かはわかりません。非同期プログラミングは、スレッド対して何も意味しません。 – Lee

15

ザ・ジャバスクリプト・モデルは、シングル・スレッドです。非同期呼び出しはではなく、新しいスレッドですが、既存のスレッドに割り込みます。これは、カーネル内の割り込みに似ています。

はい、1つのスレッドで非同期呼び出しを行うのは理にかなっています。これについて考える方法は次のとおりです。単一のスレッド内で関数を呼び出すと、現在のメソッドの状態がスタック(つまりローカル変数)にプッシュされます。サブルーチンが呼び出され、最終的に戻ります。その時点で、元の状態がスタックからポップされます。

非同期コールバックでは、同じことが起こります。違いは、サブルーチンが呼び出されるのは、現在のコードがサブルーチンを呼び出すのではなく、システムによって呼び出されることです。

+1

>>非同期呼び出しは新しいスレッドではありません<< - これは誤解を招く陳述です。 JSが新しいスレッドでXHRリクエストを処理するのを妨げるものは何も知らない。私はあなたが新しいスレッドが仕様によって保証されていない、または示唆されていないことを意味していると思いますが、システムによって実装される方法は間違いありません。 – Lee

4

多くのGUIアプリケーションでは、非同期呼び出し(JavaのinvokeLaterなど)は、GUIスレッドキューにRunnableオブジェクトを追加するだけです。 GUIスレッドはすでに作成されており、新しいスレッドは作成されません。しかし、スレッドは、非同期システムでは厳密には要求されません。たとえば、select/poll/kqueueなどを使用してソケットに非ブロック呼び出しを行うlibeventを取ると、コードにコールバックが発生し、スレッドはまったく必要ありません。

5

カップルノート:

XMLHttpRequest Sは、デフォルトでは非ブロッキングです。 send()メソッドは、要求が基礎となるネットワークスタックにリレーされた直後に戻ります。サーバーからの応答は、他の優れた回答で説明されているように、イベントループでのコールバックの呼び出しをスケジュールします。

これは新しいスレッドを必要としません。基底ソケットAPIはJavaでjava.nio.channelsに似て選択できます。

open()に第三のパラメータとしてfalseを通過させることによって同期XMLHttpRequestオブジェクトを構築することが可能です。これにより、サーバからの応答が受信されるまで、send()メソッドがブロックされ、イベント待ち時間がネットワーク待ち時間になり、ネットワークタイムアウトまでブラウザがハングする可能性があります。これはBad Thing™です。

Firefox 3.5は、Workerクラスの正直から神までのマルチスレッドJavaScriptを導入します。バックグラウンドコードは完全に別個の環境で実行され、イベントループのコールバックをスケジュールすることによってブラウザウィンドウと通信します。

+0

あなたが「サーバーからの応答がイベントループでコールバックの呼び出しをスケジュールする」と言ったとき、/どのスレッドがイベントループにイベントを入れてコールバックを呼び出すのか? – Yiling

+1

@Yilingイベントは、JavaScriptを実行するスレッドではなく、ブラウザ内部のI/Oスレッドによって作成されます。 – Matthew

2

いいえ、複数のスレッドが関与します。

非同期呼び出しが別のスレッドを起動して作業を行うか、すでに実行中の別のスレッドのキューにメッセージをポストする可能性があります。呼び出し元は処理を続行し、呼び出し先はメッセージを処理した後にコールバックします。

このコンテキストで同期呼び出しを行いたい場合は、メッセージを送信し、コールバックが発生するのを積極的に待つ必要があります。

要約:複数のスレッドが関与しますが、必ずしも新しいスレッドを作成するとは限りません。

2

javascriptについてはわかりませんが、Windowsフォームの世界では、複数のスレッドを使わずに非同期呼び出しを行うことができます。これは、Windows Message Pumpの操作方法と関係があります。基本的にWindowsフォームアプリケーションは、Windowsがイベントについて通知するメッセージを配置するメッセージキューを設定します。たとえば、マウスを動かすと、そのキューにメッセージが配置されます。 Windows Formsアプリケーションは、それにスローされたすべてのメッセージを消費する無限ループになります。各メッセージに含まれる内容に応じて、ウィンドウの移動、再ペイント、またはユーザー定義メソッドの呼び出しなどが行われます。メソッドへの呼び出しは、代理人によって識別されます。アプリケーションがキュー内のデリゲート・インスタンスを検出すると、デリゲートが参照するメソッドをうまく起動します。

新しいスレッドを作成せずに何らかの非同期作業を開始するメソッドを使用している場合は、Control.BeginInvokeメソッドを使用してデリゲートインスタンスをキューに配置するだけです。これは実際にはマルチスレッドではありませんが、非常に小さな作業をキューに投げ込むと、マルチスレッドのように見えます。一方、実行に時間のかかる方法を指定すると、メソッドが完了するまでアプリケーションがフリーズします。これは、何かを行っているにも関わらず、詰まったアプリケーションのように見えます。

関連する問題