Эффективность того, в то время как (истинные) ServerSocket Слушают

Я задаюсь вопросом если типичное while(true) ServerSocket слушают, цикл берет все ядро, чтобы ожидать и принять соединение клиента (Реализовывая выполнимый и использующий Thread .start())

Я реализую тип кластера распределенных вычислений, и каждому компьютеру нужно каждое ядро, которое он имеет для вычисления. Главный узел должен связаться с этими компьютерами (вызывающий статические методы, которые изменяют функционирование алгоритма).

Причина я должен использовать сокеты, происходит из-за кросс-платформенного / межъязыковые возможности. В некоторых случаях PHP будет вызывать эти статические методы Java.

Я использовал профилировщика Java (YourKit), и я вижу, что мой рабочий ServerSocket слушает поток, и он никогда не спит, и он всегда работает. Существует ли лучший подход, чтобы сделать то, что я хочу? Или, производительность совершит нападки быть незначительной?

Не стесняйтесь предлагать любое предложение, если можно думать о лучшем пути (я попробовал RMI, но это не поддерживается межъязыковое.

Спасибо все

9
задан Natan Streppel 11 June 2014 в 03:32
поделиться

4 ответа

Если вы имеете в виду что-то вроде этого:

while (true) {
  Socket socket = server.accept();
  /* Do something with socket... */
}

тогда, нет, вызов accept () не «берет все ядро». Это блокирующий вызов, который позволяет ЦП планировать работу другого потока до тех пор, пока клиент не подключится. После возврата вызова accept () текущий поток будет запланирован для выполнения и будет использовать ЦП до тех пор, пока он не заблокируется на accept () в следующей итерации цикла.

Чтобы избежать чрезмерного увеличения количества запросов других клиентов, другой поток обычно обрабатывает взаимодействие с недавно принятым Socket , оставляя один поток сосредоточиться на приеме новых клиентов. Поток обработки сокетов может обрабатывать множество сокетов, используя NIO, или он может быть выделен для одного сокета, что намного проще кодировать, но не будет хорошо масштабироваться после многих сотен одновременных подключений.

9
ответ дан 4 December 2019 в 12:17
поделиться

Возможно, вы захотите взглянуть на Java 1.4 nio библиотеки и в частности ServerSocketChannel. Я использую это очень успешно для реализации эффективного сервера, ключевые биты кода:

Selector selector = Selector.open();

ServerSocketChannel server= ServerSocketChannel.open();
server.socket().bind(new java.net.InetSocketAddress(port));
server.configureBlocking(false);
SelectionKey serverKey = server.register(selector, SelectionKey.OP_ACCEPT);

// start listening thread
new Thread(listener).start();

И прослушиватель - это просто цикл, который выполняется:

selector.select(1000); // listen for one second max
Set<SelectionKey> keys = selector.selectedKeys();

if (keys.size()>0) {
    handleKeys(keys);
}
5
ответ дан 4 December 2019 в 12:17
поделиться

Дайте ядру немного поспать. В вашем методе Runnable добавьте что-то вроде

Thread.sleep(250); // milliseconds 

в каждый цикл.

Это должно значительно снизить загрузку ЦП

Изменить: плохая идея, см. Комментарии, извините, моя ошибка


И: не используйте while (правда). это ужасный дизайн, поскольку семантика предполагает, что в конечном итоге истина перестанет быть правдой. Обычно вы хотите запросить некоторую изменчивую или атомарную переменную из основного потока

public class MyClass {

class MyRunnable implements Runnable {

    public void run() {
        while (MyClass.this.keepGoing.get()) {
            // listen();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // deal with exception
            }

        }
    }

}

private final AtomicBoolean keepGoing = new AtomicBoolean(true);

}

. Таким образом, основной поток имеет способ остановить поток слушателя.

0
ответ дан 4 December 2019 в 12:17
поделиться

Я использовал java профилировщик (YourKit), и я вижу, что мой запущенный поток прослушивания ServerSocket никогда не спит и всегда работает.

По сути, профайлер вводит вас в заблуждение.

Я предполагаю, что ваш код выглядит так:

ServerSocket server = ...
// configure server socket

try {
    while (true) {
        Socket socket = server.accept();
        // do something with socket (and close it afterwards!)
    }
} catch (InterruptedException ex) {
    // we're outta here!
}

Это не потребует значительных ресурсов ЦП ... если вы не сделали что-то патологическое, например вызов ServerSocket.setSoTimeout (int) с небольшим таймаутом.

3
ответ дан 4 December 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: