Очистка потока Java Poller перед завершением работы JVM - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть Java-приложение, в котором есть несколько бесконечно запущенных потоков, опрашивающих внутреннюю базу данных. Когда JVM выключается (через weblogic UI), мне нужно выполнить некоторые операции очистки для каждого из потоков, например, подключение к БД и установка статуса выполнения транзакций с «в процессе» на «необработано».

Есть ли способ написать метод в каждом потоке, который будет вызываться, когда поток будет остановлен JVM?

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

1 Ответ

0 голосов
/ 19 сентября 2018

Поскольку у вас есть доступ к этим потокам (я имею в виду, что вы можете изменить их код), вы можете:

  1. Не разрешать пользователю прекращать выход из приложения обычным способом.Вы остановите это для него, как только он попросит вас сделать это.Это где вам нужен крюк.Например, если приложение основано на JFrame, тогда добавьте хук windowClosing(), чтобы изящно остановить выполнение Thread с и в то же время установить для операции закрытия кадра по умолчанию значение DO_NOTHING_ON_CLOSE .Посмотрите на мой код в этом ответе ниже ...
  2. Поместите остановочный флаг в бесконечные петли, делая их конечными .
  3. Когда произойдет отключение, измените эти флаги так, чтобы каждый Thread выходил из цикла.
  4. Когда вне цикла Thread внесет любые необходимые изменения (с полным доступом ко всем его переменным)) и затем выйдите из метода run().
  5. Между тем, в основных Thread (т. е. Thread, которые отмечали все остальные Thread s для остановки), вы собираетесь join() каждый конечный Thread.
    Этот метод позволяет дождаться полного выполнения Thread (т. Е. Выйти из метода run()).
  6. Наконец, основной Thread, собирается вызвать , например, System.exit(0);, чтобы выйти из всего приложения, потому что это, предположительно, последнее желаемое действие пользователя.

Примечание: предполагается, что пользовательсобирается закрыть приложение с обычными действиями.Если, например, пользователь собирается, например, убить приложение через диспетчер задач Windows, этот подход не будет работать.Я не знаю о перехватах отключения на Thread s ...

Следующий пример кода (читайте комментарии):

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GraceDown {
    private static class MyThread extends Thread {
        private boolean keepGoing = true; //This is the stopping flag.
        private final int i; //In this case i marks the 'id' of the Thread, but it is also an arbitary variable that the Thread has acccess in its final moments...

        public MyThread(final int i) {
            this.i = i;
        }

        private synchronized boolean isKeepGoing() {
            return keepGoing; //Tells if we should exit the loop and start the stopping operation...
        }

        public synchronized void startShutdown() {
            keepGoing = false; //Tells we should exit the loop and start the stopping operation.
        }

        @Override
        public void run() {

            while (isKeepGoing()) { //After every complete loop, we check the if we can go on.
                //Your 'infinite' loop actions go in here:
                try { Thread.sleep(1000); } catch (final InterruptedException ie) {}
                System.out.println("Thread " + i + " running...");
            }

            //Your gracefull shutdown actions go here...
            System.out.println("Thread " + i + ": my stopping actions go here! Look, I have access to all my variables (such as i)! ;)");
        }
    }

    public static void main(final String[] args) {
        //Create and start the Threads:
        final MyThread[] myThreads = new MyThread[5];
        for (int i = 0; i < myThreads.length; ++i)
            myThreads[i] = new MyThread(i);
        for (int i = 0; i < myThreads.length; ++i)
            myThreads[i].start();

        final JFrame frame = new JFrame("Lets close me...");
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); //IMPORTANT STEP! This means we are going to close the application instead of it being closed automatically when the user presses to close the window...

        //Adding the 'hook':
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(final WindowEvent wevt) {
                System.out.println("Initializing shutdown...");
                //This is where the thread is going to stop all others...
                for (int i = 0; i < myThreads.length; ++i)
                    myThreads[i].startShutdown();

                //Wait for all threads to stop:
                for (int i = 0; i < myThreads.length; ++i)
                    try { myThreads[i].join(); } catch (final InterruptedException ie) { System.err.println("Error gracefully shutdowning the Thread!!!"); }

                //Now we can exit the JVM:
                System.out.println("Exiting JVM...");
                System.exit(0); //Code '0' indicates exiting without error(s).
            }
        });

        frame.getContentPane().add(new JLabel("Close this window and the Threads will shutdown gracefully...", JLabel.CENTER));
        frame.pack();
        frame.setLocationRelativeTo(null); //Put the packed frame on the center of the default screen.
        frame.setVisible(true);
    }
}

Вышеприведенное должно напечатать что-то вроде этого:

Тема 1 запущена ...
Тема 4 запущена ...
Тема 0 запущена ...
Тема 2 запущена ...
Тема 3 запущена ...
Тема3 работает ...
Поток 4 запущен ...
Поток 2 запущен ...
Поток 1 запущен ...
Поток 0 запущен ...
Инициализация завершения ...
Тема 2 запущена ...
Тема 2: мои действия по остановке идут сюда!Смотри, у меня есть доступ ко всем моим переменным (например, я)!;)
Тема 0 запущена ...
Тема 0: мои действия по остановке идут здесь!Смотри, у меня есть доступ ко всем моим переменным (например, я)!;)
Тема 1 запущена ...
Тема 4 запущена ...
Тема 3 запущена ...
Тема 3: мои действия по остановке идут здесь!Смотри, у меня есть доступ ко всем моим переменным (например, я)!;)
Тема 4: мои останавливающие действия идут сюда!Смотри, у меня есть доступ ко всем моим переменным (например, я)!;)
Тема 1: мои останавливающие действия идут сюда!Смотри, у меня есть доступ ко всем моим переменным (например, я)!;)
Выход из JVM ...

Это минимальное решение, которое я вижу в вашей проблеме, как вы ее описали.

...