16

基本的な質問があります。SelectableChannelのregisterメソッドが呼び出しをブロックする理由と方法。シナリオを提供させてください。

次のように、RegisterクラスにSelectorオブジェクトを作成しました。

private static Selector selector = Selector.open();

同じクラス(Register)にチャンネルをセレクターに登録するメソッドもあります。

public static SelectionKey registerChannel(SelectableChannel channel, int ops)
                             throws IOException {
   channel.configureBlocking(false);
   return channel.register(selector, ops);
}

また、Requestという名前の別のクラスがあります。このクラスには、チャネルからデータを読み取り、処理し、次のメソッドを呼び出してチャネルを登録するメソッドがあります。

selectonKey = Register.register(socketChannel, SelectionKey.OP_READ);

ここで、この時点でスレッドはブロックされ、何を待っているのかがわかりません。セレクターが開いていることを確認しました。これを解決する方法を理解するために、私にいくつかの助けを提供してください。解除できるロックはありますか?

任意の入力をいただければ幸いです。

私が説明したことに加えて。さらにテストを行ったところ、Register.registerメソッドが同じスレッドから呼び出された場合は登録できますが、その後、他のスレッドがメソッドを呼び出そうとしても、スレッドは先に進みません。

4

5 に答える 5

38

これは、ほとんどの NIO 実装の基本的な機能であり、ドキュメントからは明らかではありません。

選択を行っている同じスレッドからすべての登録呼び出しを行う必要があります。そうしないと、デッドロックが発生します。通常、これは登録/登録解除/興味の変更のキューを提供することによって行われ、そこに書き込まれ、selector.wakeup() が呼び出されます。選択中のスレッドが起動すると、キューがチェックされ、要求された操作が実行されます。

于 2010-02-01T19:55:14.803 に答える
0

プログラム内のすべてのスレッドのスタック トレースを印刷しようとしましたかkill -QUIT(Unix で、または Windows で Ctrl+Break を使用するjstackか、ユーティリティを使用して)。

AbstractSelectableChannel同期が必要なロックが含まれていますconfigureBlockingregisterこのロックはblockingLock()メソッドを介してアクセスすることもできるため、別のスレッドがロックを保持している可能性があり、登録呼び出しが無期限にブロックされる可能性があります (ただし、スタック トレースがないと判断が困難です)。

于 2009-06-29T09:30:59.393 に答える