Вопрос

Пожалуйста, укажите/предоставьте мне рабочий пример selector.wakeup(); метод между двумя потоками.

Я попытался создать простую программу, в которой поток ожидает метода selector.select().Второй поток создает несколько сокетов и пытается зарегистрироваться в селекторе;на котором первый поток заблокирован.

Следовательно, мне нужно использовать селектор wakeup метод, но почему-то первый поток не выходит из режима блокировки.

Javadoc метода пробуждения гласит:

Если другой поток в настоящее время блокируется в вызовах селектора. Select () или селектор. Выберите (длинные) методы, тогда этот вызов немедленно вернется.

P.S. Есть еще несколько обходных путей;один из них — 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
      }
   }
}

ВТОРАЯ ТЕМА:

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);

}
Это было полезно?

Решение

Вероятно, вы не хотите, чтобы сокет из потока 2 блокировался, если вы регистрируете его в селекторе (поскольку селекторы предназначены для неблокирующего ввода-вывода).Я думаю, что это также обычная практика, позволяющая селектору обрабатывать соединение с помощью OP_CONNECT (с использованием SocketChannel.finishConnection()).

Также похоже, что здесь может возникнуть потенциальное состояние гонки.Представьте себе такую ​​серию событий:

  1. Тема 1:селектор.выбрать()
  2. ...Время проходит ...
  3. Тема 2:Thread1.selector.wakeup()
  4. Тема 1:проверяет ключи на приемлемость
  5. Тема 1:проверяет ключи на читаемость
  6. Тема 1:петля
  7. Тема 1:селектор.выбрать()
  8. Тема 2:попробуй прописаться в селекторе (но для этого select() уже поздно)

Я бы предложил, чтобы поток 2 настроил SocketChannel, спрятал его где-нибудь, где поток 1 может добраться до него (при этом убедитесь, что вы потокобезопасны), а затем разбудите селектор, позвольте ему проверить существующие ключи в потоке 1. и пусть поток 1 зарегистрирует новый SocketChannel, прежде чем он снова вызовет Selector.select().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top