Обслуживание каждого соединения, возвращенного из accept, должно идти в отдельный поток, т. Е. В метод run()
должно быть перенесено следующее:
System.out.println(socket + " " + "welcome\n");
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String answer = input.readLine();
System.out.println(answer);
if ("hej".equals(answer)) {
System.out.println("Sacrafice accepted");
}
}
finally {
socket.close();
}
Конечно, вам нужно добавить код, который создает поток. Поскольку создание потоков является дорогостоящей задачей, а потоки можно многократно использовать, лучше всего создать несколько рабочих потоков в пуле заранее во время инициализации, а затем извлекать рабочие потоки из пула только после того, как вы примете соединение и нуждаетесь в потоке для его обслуживания. При разработке приложения вы можете обнаружить, что добавление некоторой логики для настройки размера пула потоков во время выполнения на основе нагрузки является хорошей идеей, но вам, вероятно, следует отказаться от этого на текущем этапе и просто использовать элемент конфигурации (например, командную строку). option или static final) для установки начального размера пула потоков. Вы можете найти реализации пула потоков в java.util.concurrent .
Если вы сделаете это, метод потока run()
будет очень просто ждать в цикле новых задач, и каждый раз, когда он получает задачу, он должен запускать метод этой задачи run()
. Приведенный выше код должен быть помещен в метод задачи run()
. Таким образом вы отделите потоки от задач и, следовательно, убедитесь, что потоки остаются многократно используемыми. Потокам также понадобится метод для получения задач, и этот метод должен быть потокобезопасным. Вы можете использовать одну из реализаций очереди из java.util.concurrent для хранения задач в ваших потоках между временем, которое они передают в поток для обслуживания, и временем, когда они удаляются из очереди run()
метода потока для их фактического запуска.
Такое разделение потоков и задач является еще одним случаем, когда добавление еще одного уровня косвенности решает важную проблему разработки программного обеспечения .