7

selector.wakeup();2つのスレッド間のメソッドの実例を教えてください。

スレッドがselector.select()メソッドを待機している単純なプログラムを作成しようとしました。2番目のスレッドはいくつかのソケットを作成し、セレクターに登録しようとします。最初のスレッドがブロックされます。

したがって、セレクターのwakeupメソッドを使用する必要がありますが、どういうわけか、最初のスレッドはブロッキングモードから出ません。

wakeupメソッドのjavadocには次のように記載されています。

Selector.select()またはSelector.select(long)メソッドの呼び出しで別のスレッドが現在ブロックされている場合、その呼び出しはすぐに返されます。

PS他の回避策はほとんどありません。そのうちの1つはselect(timeout)ですが、どこに間違いがあるのか​​を突き止めようとしています。

疑似コード:

最初のスレッド:

static Selector selector = Selector.open();
while(true) {
   int n = selectorGlobal.select();
   selectorKeySet = selectorGlobal.selectedKeys().iterator();
   while (selectorKeySet.hasNext()) {
      selectionKey = selectorKeySet.next();
      if (selectionKey.isReadable()) {
         //do something
      }
      if(selectionKey.isAcceptable()) {
         //accept
      }
   }
}

2番目のスレッド:

while (itr.hasNext()) { 
   data = (String) itr.next();
   String IP = data.get(0);
   String Port = data.get(1);

   SocketChannel socketChannel = SocketChannel.open();
   socketChannel.configureBlocking(true);
   boolean isConnected = socketChannel.connect(new InetSocketAddress(IP, Port));
   ClassName.selector.wakeup();
   SelectionKey selectionKey = SelectSockets.registerChannel(ClassName.selector,
                socketChannel, SelectionKey.OP_READ);

}
4

1 に答える 1

6

セレクターに登録する場合は、スレッド2のソケットをブロックしたくないでしょう(セレクターは非ブロックI / Oを対象としているため)。セレクターにOP_CONNECTでの接続を処理させることも一般的な方法だと思います(SocketChannel.finishConnection()を使用)。

また、ここで潜在的な競合状態が発生する可能性があるようです。この一連のイベントを想像してみてください。

  1. スレッド1:selector.select()
  2. ... 時を経て ...
  3. スレッド2:Thread1.selector.wakeup()
  4. スレッド1:キーの受け入れ可能性をチェックします
  5. スレッド1:キーの可読性をチェックします
  6. スレッド1:ループ
  7. スレッド1:selector.select()
  8. スレッド2:セレクターに登録してみてください(ただし、このselect()には遅すぎます)

スレッド2にSocketChannelを設定して、スレッド1が取得できる場所に隠してから(これを行うときはスレッドセーフであることを確認してください)、セレクターを起動して、スレッド1の既存のキーを確認することをお勧めします。スレッド1に、Selector.select()を再度呼び出す前に、新しいSocketChannelを登録させます。

于 2009-11-05T04:51:04.130 に答える