2009-07-10 10 views
6

私は、アプリケーションの反対側の外部システムに接続して登録したクライアントを表すクラスのオブジェクトをインスタンス化するJavaアプリケーションを作成しています。Java - 非ブロッキングソケット用の複数スレッドの複数のセレクタ

各クライアントオブジェクトには、フロントエンドとバックエンドを表す2つのネストされたクラスがあります。フロントエンドクラスは実際のクライアントから継続的にデータを受信し、フロントエンドからそのデータを受け取り、適切なフォーマットとプロトコルを使用して外部システムに送信するバックエンドクラスに指示とデータを送信しますそのシステムに必要です。

この設計では、クライアントオブジェクトの各インスタンス化をスレッドにすることを検討しています。次に、各スレッド内には当然ながら、それぞれ独自のNIOチャネル[EDIT]を持つ2つのソケット[EDIT]があり、クライアント側とシステム側はそれぞれフロントエンドとバックエンドに存在します。しかし、これにより、非ブロッキングソケットが必要になりました。私はチュートリアルhereを読んでいます。このチュートリアルでは、メインスレッドでセレクタを安全に使用して、接続されたすべてのスレッドを処理する方法について説明しています。

しかし、私が必要とするのは、複数のセレクタで、それぞれは独自のスレッドで動作します。前述のチュートリアルを読んで、Selectorのキーセットがスレッドセーフではないことを知りました。これは、ソケットとチャンネルのペアをそれぞれ持たせようとすると、自己のrepsectiveスレッドでインスタンス化された別のセレクタが競合するキーを作成する可能性があることを意味しますか?セレクタをメインスレッドに移動することはわずかな可能性がありますが、私が与えたソフトウェア要件に基づいて理想からは遠く離れています。ご協力ありがとうございました。

答えて

3

複数のセレクタを使用すると、両方のセレクタインスタンスで同じ関心(OP_READ/OP_WRITEなど)を持つ同じチャネルを登録しない限り、問題ありません。同じチャネルを複数のセレクタインスタンスに登録すると、selector1.select()がselector2.select()が関心のあるイベントを消費するという問題が発生する可能性があります。

ほとんどのプラットフォームのデフォルトのセレクタはpoll()です[ epoll()]をベースにしています。

Selector.selectは内部ROX RPC NIOチュートリアルで述べたように、私は単一の選択スレッドの使用をお勧めします、と述べint poll(ListPointer, Nfdsmsgs, Timeout) method.

 where the ListPointer structure can then be initialized as follows: 

    list.fds[0].fd = file_descriptorA; 
    list.fds[0].events = requested_events; 
    list.msgs[0].msgid = message_id; 
    list.msgs[0].events = requested_events; 

を呼び出します。 NIOの実装はプラットフォームに依存するため、あるプラットフォームで動作するものが別のプラットフォームで動作しない可能性があります。マイナーバージョン間でも問題が発生しています。 たとえば、AIX JDK 1。6 SR2はpoll()ベースのセレクタPollSelectorImplとそれに対応するセレクタプロバイダPollSelectorProviderを使用していました。 pollsetインタフェースに基づく最適化セレクタ(PollSetSelectorImpl)を使用していたAIX JDK 1.6 SR5に移動したとき、select()およびsocketchannel.close()でサーバーが頻繁にハングすることがありました。私が見る1つの理由は、(理想的なSelect Threadモデルとは対照的に)アプリケーションで複数のセレクタを開き、hereと記述されているPollSetSelectorImplの実装です。

3

この単一ソケット接続を使用する必要がある場合は、データ処理自体からチャネルとの間でデータを送受信するプロセスを分離する必要があります。チャンネルを委任する必要はありません。チャンネルはバスのようなものです。バス(チャネルを管理する単一のスレッド)は、データを読み込み、必要な情報を含む(スレッドセーフな)入力キューに書き込む必要があります。これにより、クライアントスレッドは正しいデータグラムパッケージを取得できます待ち行列。クライアントスレッドがデータを書き込むことを好む場合、そのデータは出力キューに書き込まれ、チャネルにデータを書き込むためにチャネルスレッドによって読み取られます。

この接続を使用してアクター間で予測不可能な処理時間(ブロックの主な理由)を共有するという概念から、非同期データ読み取り、データ処理、およびデータ書き込みという概念に移行します。したがって、それはもはや予測不可能な処理時間ではありませんが、あなたのデータは読み書きされます。ノンブロッキングとは、データを処理するために必要な時間があるにもかかわらず、データのストリームができるだけ一定であることを意味します。

+0

私はちょっとあなたの答えで混乱しています。あなたは、チャンネル自体がスレッドであり、チャンネルが独自のスレッドであると言っていますか、別のチャンネルクライアントからのスレッド? 私のオリジナル投稿では、各クライアントオブジェクトに2つのソケットと、アプリケーションの両側で通信する2つのチャネルがあるはずです。ノンブロッキングとノンブロッキングの概念に精通しており、多重通信の要件のために非ブロッキングを特に選択しました。 –

+1

これはうんざりしています。 :http://www.ibm.com/developerworks/aix/library/au-pollset/index.htmlより良い答えが得られます。 Threading thingamabob:これは、良いioとスレッドのパフォーマンスを望むプログラミングコンテキストで動作するように設計されています。全体の問題は、Real-Time JSRに記述されている問題によって深刻に混乱しています。上記のリンクは、問題についての情報が提供されているエンジニアによる問題の議論を行います。私は早期にテストをしましたが、そうではありません。 –

関連する問題