読み取り操作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
アクティブなチャネルによって が非常に頻繁に起動し、そのたびにキー セット全体が繰り返されるため、これは非常に非効率的です。
この問題を解決するためのより良い (より効率的な) 方法はありますか?