У вас есть серьезная проблема в вашем примере.
В Java NIO поток, выполняющий accept () , должен выполнять только accept () . Если не считать примеров, вы, вероятно, используете Java NIO из-за ожидаемого большого количества соединений. Если вы даже думаете о выполнении чтения в том же потоке, что и выборки, ожидающие неприемлемые выборки будут иметь время ожидания ожидания установления соединения. К тому моменту, когда этот один перегруженный поток доберется до принятия соединения, ОС с обеих сторон перестанут работать, и accept () завершится ошибкой.
Делайте только абсолютный минимум в цепочке выбора. Больше, и вы будете просто переписывать код, пока не сделаете только минимум.
[В ответ на комментарий]
Только в примерах игрушек чтение должно обрабатываться в главном потоке.
Попробуйте обработать:
- 300 + одновременных попыток подключения.
- Каждое установленное соединение отправляет 24 Кбайт на один сервер - то есть небольшую веб-страницу, крошечный .jpg.
- Немного замедлите каждое соединение (соединение устанавливается по коммутируемому соединению, или в сети высокая частота ошибок / повторных попыток) - так что ACK TCP / IP занимает больше времени, чем идеально (вне уровня управления ОС )
- У вас есть несколько тестовых соединений, отправляйте один байт каждые 1 миллисекунду. (это моделирует клиента, который имеет свое собственное состояние высокой нагрузки, поэтому генерирует данные с очень медленной скоростью.) Поток должен тратить почти столько же усилий на обработку одного байта, сколько и 24 КБ.
- Некоторые соединения должны быть разорваны без предупреждения (проблемы с потерей соединения).
На практике соединение должно быть установлено в течение 500-1500 мс, прежде чем попытка машины прервет соединение.
В результате всех этих проблем один поток не сможет установить все соединения достаточно быстро, пока машина на другом конце не откажется от попытки подключения. Чтения должны быть в другом потоке. период.
[Ключевой пункт]
Я забыл, чтобы действительно быть ясно об этом. Но у потоков, делающих чтение, будет свой собственный Селектор. Селектор, используемый для установления соединения, не должен использоваться для прослушивания новых данных.
Добавление (в ответ на утверждение Гнарли о том, что во время вызова Java для чтения потока фактически не происходит ввода-вывода.
Каждый слой имеет определенный размер буфера. Как только этот буфер заполнен, IO останавливается. Например, буферы TCP / IP имеют от 8К до 64К буферов на соединение. Как только буфер TCP / IP заполняется, принимающий компьютер сообщает отправляющему компьютеру остановиться. Если принимающий компьютер не обрабатывает буферизованные байты достаточно быстро, отправляющий компьютер прервет соединение.
Если принимающий компьютер обрабатывает буферизованные байты, отправитель продолжит потоковую передачу байтов, , пока выполняется вызов чтения java io .
Кроме того, осознайте, что первый поступающий байт вызывает «байты, доступные для чтения» на селекторе. Там нет никаких гарантий относительно того, сколько прибыло.
Размеры буфера, определенные в коде Java, не имеют отношения к размеру буфера ОС.