Изящно закрывая приложение при получении сигнала - PullRequest
0 голосов
/ 23 октября 2018

Я думаю, как написать обработчик сигнала, который бы информировал главный поток о необходимости выхода.

Я думаю следующее:

1) использовать следующий коддля перехвата сигнала

SignalHandler handler = new SignalHandler () {
      public void handle(Signal sig) {
        System.out.println("Signal " + sig);
        System.out.println("Shutting down...");

        ServiceLocator.ProgramState().setMustExit();

        System.exit(0);
      }
    };
Signal.handle(new Signal("INT"), handler);
Signal.handle(new Signal("TERM"), handler);

2) Установите объект ProgramState для указания необходимости выхода: ServiceLocator.ProgramState (). setMustExit ();

3) поместите следующий код в некоторыечасти программы, чтобы проверить, говорит ли мне ProgramState о выходе:

if (ServiceLocator.ProgramState().mustExit()) {
    throw new MustExitException();
}

исключение будет перехвачено основным потоком, который завершится чисто.

Я не очень люблю бросатьисключение, как я собираюсь сделать, но это кажется быстрым способом достижения моей цели.

Есть ли другие способы изящного выхода?

1 Ответ

0 голосов
/ 24 октября 2018

Основной поток обычно ожидает какого-либо события / уведомления (прямо или косвенно), которое не позволяет ему немедленно завершить программу

Чистое завершение работы позволило бы основному потоку узнать, что пришло время "двигаться дальше"."либо прерывая его, либо уведомив об этом.Как часть пути завершения выполнения программы после этой точки, он должен позаботиться о «завершении» других важных частей программы (в большинстве случаев их нет).

Если приложениеоднопоточный ... ну, наверное, не должно быть.Логика выполнения ядра должна быть отделена от основного потока.

Spring IOC / Guice (регулятор Netflix) существуют специально для достижения лучшего контроля жизненного цикла над вашим графом объектов.

И то, и другое может помочь вам в создании реализации, в которой начальная загрузка / завершение работы / компонентное соединение отделено от реальной логики приложения и обеспечивают удобный способ управления жизненным циклом ваших различных объектов / классов.

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

Например, если вы решите работать с Spring, вы определите обработчик сигнала как bean-компонент, внедрите / автоматически подключите его с помощью ConfigurableApplicationContext экземпляр и вызовите его close() метод после получения желаемого сигнала.Это приведет к тому, что все bean-компоненты с пружинным подключением будут выполнять определенное (если определено) поведение отключения / уничтожения

Будет работать обработка сигналов PS, но есть более конкретные способы передачи сообщений о завершении работы (см. ZeroMq / JeroMQ, дляпример сообщения без посредников) из внешних источников.

...