2016-07-15 2 views
-1

Reactor Patternを適用したJava NIOを使用した単純なサーバークライアントアプリケーションを作成しています。私の理解のために、(例:OP_ACCEPT、OP_READ、OP_WRITE)を収集するのはReactorクラスです。個別のスレッドでイベントハンドラをディスパッチする

相対的なEventHandlerは特定のタスクを担当するので、ハンドラは別々のスレッドで非同期に実行する必要があります。ここ

はコードです:enter image description here

私はこれを実行すると、それはいくつかの問題を示し、whileループを実行し続けるには、とSelectorは(1,4,16)のセットreadyOpsを返し続けます。私はそれがAcceptHanndlerがブロック方法でOP_ACCEPTを処理しなかったためだと思うので、イテレータでキーが削除された場合は、select()の後に再び表示されます。だから私はイベントを取るべきではありません。

edge-triggeredlevel-triggeredモデルのコンセプトが私の心に浮かんでいます...セレクターはlevel-triggeredモデルで稼働していますか?

+0

セレクタの全ポイントは別のスレッドを使用する必要はありません。 – EJP

+0

Selectorのポイントは、1つのスレッドで複数のソケットを管理することです。クライアントごとにスレッドを使用しませんでした。 – JasonHuang

+0

あなたはそれよりはるかに悪いです。基本的にセレクタイベント*ごとにスレッド*を使用しています。現在のスレッドでハンドラーを実行し、データベースアクセス、* after *の処理を完了した長時間実行するイベント、またはイベントが現在のスレッド内のどこにあっても補助スレッドを使用する必要があります。あなたの基本的なモデルは壊れています.. – EJP

答えて

1

はい、セレクタがレベルトリガされています。あなたのケースでは、標準のワークフローは次のようになります:チャンネルが受け入れ可能であることを検知した後、セレクタからそのキーをキャンセルし、そのキーをイベントハンドラスレッドに渡した後にのみキャンセルします。イベントハンドラスレッドはacceptを完了し、1)OP_ACCEPTのためにもう一度サーバソケットを登録します。 2)実装するプロトコルに応じて、OP_READおよび/またはOP_WRITEの受け入れられたクライアントソケットを登録します。あるいは、メインスレッドでacceptを完了することもできます(パフォーマンス上の理由から、接続しているクライアントがいる場合)。

実際には、操作の種類によってスレッドを区別することはスケーラブルではなく、データのローカリティが低いためSMPシステムでパフォーマンスが低下する可能性があります。各クライアントソケットを単一のスレッドにロックする方がよい。高性能Javaサーバーは通常、受け入れ専用の1つのスレッド(そこにはただ1つのServerSocketが登録されています)とクライアントソケットを扱うためのN個のワーカースレッドを実装して実装されています。新しいクライアントが

  • 完了が
  • 、新たに受け入れられたクライアントソケットの最も負荷のワーカースレッドと転送所有権を選択受け入れる到着するまで、選択中

    1. ブロック():スレッドを受け入れるとループで動作します各ワーカースレッドは、独自のセレクタとクライアントソケットのセットを持ち、これらのソケットの読み書きを行います。

    +0

    あなたの返信のためのtks:D。 Selectorが 'level-triggered'の場合、次の' select() 'の前にすべてのイベントハンドラを完了しなければなりません。私が選んだこのスレッドモデルは決してうまくいかないでしょう...実際には、すべての 'event'をスレッドで保持するのではなく、読み書き操作ごとにAIOを使うことができるのでスレッドを保持しません。 'Selector'は1つのスレッドをとり、' event collect'に焦点を当てます... – JasonHuang

    関連する問題