Как я могу дождаться окончания работы HttpServer (т.е. присоединиться к фоновому потоку)? - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть этот код:

import com.sun.net.httpserver.HttpServer;

...

DatabaseConnection dbConnection = ...
HttpServer server = HttpServer.create();
server.createContext("/endpoint", new MyHandler(dbConnection));
server.start();

// What should I do here in order to wait until `server` stops?

dbConnection.close()

Документация com.sun.net.httpserver.HttpServer#start гласит: «Запускает этот сервер в новом фоновом потоке.»

Я бы хотел вызвать dbConnection.close() после того, как фоновый поток server перестанет выполняться (что может произойти, например, из-за того, что я нажимаю Ctrl + C). Но в документации HttpServer не указан какой-либо способ доступа к фоновому потоку, поэтому я не могу понять, как .join().

Как мне дождаться фон HttpServer нить останавливается? Или есть другой способ, которым я могу гарантировать, что dbConnection.close() вызывается, когда мое приложение закрывается?

Ответы [ 3 ]

0 голосов
/ 19 февраля 2020

Лучший способ гарантировать, что что-то всегда будет закрыто, - это использовать Try with Resources, эта конструкция всегда будет закрывать все, что Closeable передано в скобках, когда закончится выполнение блока кода.

Вот пример.

try(dbConnection) {
// do any sort of work inside this block. 
}

При этом dbConnection или Closeable будут закрыты таким образом.

Попробуйте с ресурсами https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

0 голосов
/ 19 февраля 2020

Сервер не остановится сам по себе. Вы должны сказать это, чтобы остановить. Согласно документации, для этого есть метод stop(int delay).

Так что ваш вопрос должен быть «как мне ждать в моей программе, пока я не скажу серверу остановиться?»

Мало Опции:

  • Подождите, пока пользователь нажмет клавишу. Сверху: очень просто. Недостаток: нельзя использовать для фоновых сервисов.
  • Дождаться завершения процесса Java (используйте перехватчики завершения работы); заметьте, однако, что это не самый лучший вариант, так как вы имеете ограниченный контроль над порядком, в котором вызываются перехватчики завершения работы, и JVM в любом случае может быть жестко убита, поэтому может оказаться невозможным добиться того, чего вы хотите.
  • Дождитесь какого-нибудь другого внешнего события - запроса по специальному URL, времени ожидания, сигнала ОС, появления назначенного файла в указанном каталоге и т. Д. c.
  • Использовать какое-либо межпроцессное взаимодействие (разделяемая память с именем каналы, сокеты, потоки, JMS et c.) для внешней связи с вашей программой. Таким образом, вы можете создать отдельную программу, которая будет подключаться к сокету и отправлять команду «EXIT» на серверную программу. Когда вы получаете команду «EXIT» в вашей серверной программе, вы выключаете сервер, закрываете соединение и выходите из основного метода.

Последний вариант самый лучший и самый чистый, но он требует немного больше работы. Он также очень универсален, потому что вы можете расширить набор команд, включив в него другие полезные вещи - перезагрузку файла конфигурации сервера, добавление или удаление сопоставлений URL во время выполнения, получение статистики службы и так далее. Это, например, как Apache работает.

0 голосов
/ 19 февраля 2020

Один из способов обеспечить закрытие dbConnection при завершении процесса Java - добавить хук отключения:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    dbConnection.close();
}));

Чтобы использовать этот подход, dbConnection должно быть эффективно final чтобы его можно было захватить в лямбду.

...