@Shiftuia
Java-программист

Как происходит остановка java приложения?

Добрый день

У нас есть многопоточное java приложение, работающее с web и базой. Мы шлем ему kill pid.
Как произойдет завершение текущих работающих потоков?
Можно ли с помощью try-catch выполнить что-то при остановке, например отослать запрос на адрес или записать что-то в базу?
Что произойдет с java приложением при вызове kill -9 ?
  • Вопрос задан
  • 449 просмотров
Решения вопроса 2
@distrik
Programador
Один из классических способов обработки остановки java-приложения, как сказали выше - Runtime.getRuntime().addShutdownHook. В свою очередь в нем можно подать команду на остановку всем остальным потокам, либо используя флаг "interrupt" класса Thread, либо используя в рабочих потоках предусмотрительно заведенный собственный флаг остановки.

Соответственно, останавливаемые потоки должны либо периодически проверять флаг остановки, либо корректно обрабатывать InterruptedException.

Пример с флагом "interrupt"

public static void main(String[] args) {
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      Thread.getAllStackTraces().keySet().stream()
          //Не стоит останавливать поток в котором отрабатывает хук, а тем более пытаться заджойниться
          .filter(thread -> !thread.equals(Thread.currentThread()))
          //Демоны предполагают безопасное завершение в любой момент, останавливать их не нужно
          .filter(thread -> !thread.isDaemon())
          //Устанавливаем флаг "interrupt" для всех остальных 
          .peek(Thread::interrupt) 
          .peek(thread -> System.out.println(thread.getClass()))
          .forEach(thread -> {
            try {
              thread.join(); //Ждем завершения всех потоков, которым установлен флаг "interrupt"
            } catch (InterruptedException e) {
              // ...
            }
          });
    }));
    
    while (true) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        System.out.println("Thread was interrupted once");
        //После перехвата исключения флаг "interrupt" возвращается в исходное состояние, поэтому его нужно установить снова
        Thread.currentThread().interrupt(); 
        break;
      }
    }

    while (true) {
      try {
        Thread.sleep(100); // Мы бы зависли здесь, если бы не установили флаг "interrupt" повторно
      } catch (InterruptedException e) {
        System.out.println("Thread was interrupted");
        Thread.currentThread().interrupt();
        break;
      }
    }
    
    while (!Thread.currentThread().isInterrupted()) {
      doSomeUninterruptableWork();
    }
  }
Ответ написан
saboteur_kiev
@saboteur_kiev Куратор тега Linux
software engineer
try-catch вполне можно использовать для стандартного 15-го (SIGTERM) сигнала (kill pid)

но 9й сигнал перехватить нельзя - ядро системы прибьет процесс сразу, try/catch будет проигнорирован.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы