Поток Java блокируется при регистрации канала с помощью селектора, когда вызывается select (). Что делать?
==========================================================================================================

У меня есть основной вопрос. Почему и как метод регистра SelectableChannel может быть при блокировании вызова.
Позвольте мне представить сценарий.

Я создал объект Selector в классе Register следующим образом.

```
<code>private static Selector selector = Selector.open();
</code>
```

У меня также есть метод в том же классе (Регистрация), чтобы зарегистрировать канал с помощью селектора.

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

И есть другой класс с именем Request, у которого есть метод, который читает данные из каналов, обрабатывает и вызывает следующий метод для регистрации канала.

```
<code>selectonKey = Register.register(socketChannel, SelectionKey.OP\_READ);
</code>
```

Здесь на этом этапе поток заблокирован, не давая понять, что он ждет.
Я проверил, что селектор открыт. Пожалуйста, предоставьте мне некоторую помощь, чтобы понять, как я могу решить эту проблему. Есть ли замок, который я могу снять.

Любой вклад будет оценен.

Добавление к тому, что я описал. Дальнейшие тесты показали, что если метод Register.register вызывается из того же потока, он может зарегистрироваться, но после этого, если какой-то другой поток пытается вызвать метод, поток не продвигается.

В том же потоке, в котором вы запускаете цикл выбора, есть ReentrantLock:

Затем, когда вам нужно зарегистрироваться в селекторе, сделайте что-то вроде этого:

Наконец, во время вашего цикла, который вы вызываете accept (), что-то вроде этого:

А затем продолжайте с остальной логикой.

Эта конструкция гарантирует, что`register()` вызов не будет заблокирован, гарантируя, что никогда не будет другого`select()` между соответствующими`wakeup()` а также`register()` звонки.



`register` вызывает поток селектора, но вы не должны использовать`selector.wakeup` как это представило бы условия гонки (представьте, что поток селектора занят обработкой других регистраций и вашего`wakeup` не разбудить никого). К счастью, Java NIO предоставляется`Pipe` так что вы можете позволить селектору слушать оба`register` звонки и другие события.

По сути, вот что нужно сделать:

Вот[полный рабочий пример](https://github.com/shadowsocks/shadowsocks-android/blob/e1553da4c6c5e3636645d8b8c2d127559b45f6e2/core/src/main/java/com/github/shadowsocks/net/ChannelMonitor.kt).



е (используя либо`kill -QUIT` в Unix или Ctrl + Break в Windows или с помощью`jstack` полезность)?

`AbstractSelectableChannel` содержит замок, на котором`configureBlocking` а также`register` нужно синхронизировать. Этот замок также доступен через`blockingLock()` метод, и поэтому другой поток потенциально может удерживать блокировку, вызывая блокировку вашего регистрационного вызова на неопределенный срок (но без трассировки стека это трудно сказать).



Ваш селекторный цикл должен выглядеть так:



 которая не очевидна из документации.

Вам нужно сделать все зарегистрированные вызовы из той же ветки, которая делает ваш выбор, или возникнут взаимоблокировки. Обычно это делается путем предоставления очереди регистрации / отмены регистрации / изменения процентов, которая записывается в, а затем вызывается selector.wakeup (). Когда выбранный поток просыпается, он проверяет очередь и выполняет любые запрошенные операции.