Как сделать так, чтобы длинная нить Java никогда не умирала - PullRequest
0 голосов
/ 24 января 2020

У меня есть длинный поток, который выполняет домашние задачи. Сбой потока трудно обнаружить, поскольку система не будет немедленно затронута. Я хочу убедиться, что эта тема никогда не умирает. Насколько я понимаю, пока код перехватывает все (Throwable), он никогда не будет d ie. Вот пример кода:

while (true) {
    try {
        // house keeping logic
    } catch (Throwable t) {
        // do not do anything
    }
}

Правильно ли мое понимание? Есть ли лучший способ размещения длинных фоновых задач? Я знаю, что ScheduledExecutorService может периодически планировать задачи, но если задаче необходимо постоянно проверять какой-либо ресурс, возможно, более эффективно просто поместить все в какое-то время l oop.

Ответы [ 3 ]

1 голос
/ 24 января 2020

Вы не можете иметь гарантированную длительную нить. Тем не менее, вы можете повторно вызывать логи c, если с вашим потоком что-то не так.

Что вы можете сделать, так это иметь наблюдатель, который будет проверять, работает ли поток каждые x минут.

Обратите внимание, что наблюдатель не сможет работать, если JVM выключится или выйдет из строя. Если вы хотите перезапустить поток, даже если JVM завершает работу, вам необходим внешний мониторинг. Для этого вы можете использовать такие инструменты, как supervisord.

public class LongRunningThread extends Thread {
    private volatile boolean IS_RUNNING = true;

    @Override
    public void run() {
        while (IS_RUNNING) {
            try {
                // actions
                this.houseKeep();
            } catch (Exception e) {
            }
        }
    }

    private void houseKeep() {
        // housekeeping logic here
    }

}

class ThreadWatcher {
    private Thread threadToBeWatched;

    public ThreadWatcher(Thread threadToBeWatched) {
        this.threadToBeWatched = threadToBeWatched;
    }

    @Scheduled(cron = "*/1 * * * *")
    public void checkStatus() {
        if (!threadToBeWatched.isAlive()) {
            // Logic to restart the thread.
        }
    }
}
0 голосов
/ 24 января 2020

Несколько моментов:

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

Во-вторых, редко можно опрашивать изменения таким образом без какой-либо задержки. Типичный сценарий может потребовать от вас, например, закрыть соединения с машинами, которые не ответили в течение 1 минуты. Для такого рода l oop вам не нужно постоянно проверять, как будет делать вышеупомянутый l oop. По крайней мере, вы должны включить вызов Thread.sleep(), чтобы предотвратить чрезмерное использование ресурсов. (Это еще одна проблема, с которой ScheduledExecutorService хорошо справляется).

Наконец, вы должны включить какой-нибудь способ изящно выйти из l oop, когда ваше приложение завершится. Достаточно простого boolean running = true; для класса, и вы затем измените свой l oop на: while (running) {...}. Если вы хотите выйти, просто установите running = false; и ваш l oop выйдет.

0 голосов
/ 24 января 2020

Если в служебную логику c входят некоторые задачи, которые можно классифицировать как периодические c задачи (например, проверять подключение к какой-либо службе один раз в 20 секунд), тогда вам лучше использовать TimerTask

Некоторые примеры могут быть полезны для планирования задач.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...