1

読み取り操作Selectorで複数のタイムアウトを選択する Java NIOがあるとします。SocketChannels

Selector selector = Selector.open();
channel1.register(selector, SelectionKey.OP_READ);
channel2.register(selector, SelectionKey.OP_READ);
channel3.register(selector, SelectionKey.OP_READ);
channel4.register(selector, SelectionKey.OP_READ);
// ... maybe even more ...

while (true) {
    if (selector.select(TIMEOUT) > 0) {
        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
            SelectionKey key = iterator.next();
            if (key.isValid() && key.isReadable())
                read(key);
            iterator.remove();
        }
    } else {
        // All channels timed-out! Cancel and close them all
        cancelAndCloseAll(selector.keys());
    }
}

特定の時間アイドル状態になった場合、チャネルをキャンセルして閉じる必要があるため、selector.select(TIMEOUT)このメソッドを使用しています。

しかし、非常にアクティブなチャネルがいくつかある場合、これは機能しません。これらのアクティブなチャネルはselectタイムアウトすることはありませんが、他のすべてのチャネルはアイドル状態になる可能性があります...

これに対する素朴な解決策は次のとおりです(ここでも言及されています):

メソッドSelectionKeyを使用して、アクティビティの最後の時刻を各チャネルに添付します。key.attach(object)選択が成功するたびに、すべての準備完了キーのアクティビティ時間を更新します。次に、すべてのキーを繰り返し処理し、特定のしきい値を超えてアイドル状態になっているキーを見つけます。

selectアクティブなチャネルによって が非常に頻繁に起動し、そのたびにキー セット全体が繰り返されるため、これは非常に非効率的です。

この問題を解決するためのより良い (より効率的な) 方法はありますか?

4

2 に答える 2

1

単純なソリューションを調整できます。

  • 選択後に準備完了キーの時間を更新します
  • 特定の時間間隔が経過した場合に のみ、他のすべてのキーを反復処理します
    • グローバル変数thresholdと変数last_check_timeを保持し 、キーの準備が整うたびに現在の時刻を計算します。 (last_check_time - 現在の時刻) > thresholdの場合、 last_check_time現在の時刻に設定し、キーを反復処理します。
    • または、単一のタイマータスクを使用して反復チェックを開始します
于 2014-11-18T14:29:15.877 に答える
0

Java.util.Timer を使用し、アイドル期間後にチャネルを閉じる TimerTask を送信します。タスクが存在する場合はキャンセルし、実行前にチャネルでアクティビティを取得したら、新しいタスクを送信します。チャネルごとに見つけることができる場所に TimerTasks を保存します。たとえば、キーの添付ファイルとして保存されているセッション オブジェクトに保存します。セッション オブジェクトには、チャネルの ByteBuffer(s)、ユーザー ID など、セッションごとに必要なものがすべて保持されます。

タイマー タスクでセレクターをウェイクアップし、何も準備ができていない場合 (select() が 0 を返す) の場合にセレクター スレッドがウェイクアップに正しく対処するか、またはチャネルが動作していないことに我慢する必要がある同時実行の問題に遭遇します。セレクターが select() でブロックされている間にタイマー タスクが close() でブロックされているため、時間通りに閉じられました。

于 2013-10-08T23:17:22.490 に答える