как подключить момент, когда поток был уничтожен

#java #multithreading

#java #Многопоточность

Вопрос:

Есть ли какое-либо место для подключения, когда поток был уничтожен? Что-то вроде :

 onDestroy{
 //do something...
}
  

Редактировать:
Извините. Я должен был сформулировать это более четко.

Завершение потока происходит не потому, что вся работа выполнена, а потому, что он был уничтожен клиентским кодом, использующим ThreadGroup.destroy() . Поскольку мой синглтон создается в клиентском коде, он будет принадлежать ThreadGroup клиентского кода и в результате будет уничтожен. (На самом деле, я не очень уверен в последнем предложении …)

Комментарии:

1. Интересно, есть ли что-нибудь через JMX ?

2. что? download.oracle.com/javase/6/docs/api/java/lang/… Смотрите метод «destroy()». В нем четко сказано «группа потоков должна быть пустой, что указывает на то, что с тех пор все потоки были остановлены» ===> это означает, что он не уничтожит ни одного потока

3. Может быть, вам лучше описать нам, чего вы пытаетесь достичь. Что вы хотите, чтобы это произошло с вашим синглтоном? Почему вы хотите завершить поток?

4. @ignis, я пытаюсь найти способ, который либо предотвратит завершение моего потока, либо установит флаг, чтобы позже я создал другой поток.

Ответ №1:

Вы можете обернуть как действие, так и перехват следующим образом.

 public final class HookOnDestroy implements Runnable {
    private final Runnable action;
    private final Runnable hook;
    public HookOnDestroy(Runnable action, Runnable hook) {
          this.hook = hook;
          this.action = action;
    }

    @Override
    public void run() {
       try {
         action.run();
       } finally {
         hook.run();
       }
    }

}
  

и

 Runnable action = ...
Runnable hook = ...
new Thread( new HookOnDestroy(action,hook)).start();
  

Ответ №2:

Не существует общего способа добавить асинхронный прослушиватель к потоку, который получает уведомление, когда поток завершается. Вы можете использовать join метод для ожидания потока, но это синхронно. Или вы могли бы создать расширение класса thread, которое вызывает прослушиватели в конце своего метода run, что-то вроде:

 public abstract class NotifyingThread extends Thread {
     private final List<ThreadListeners> listeners;

     protected abstract void doRun();

     public void run() {
         doRun();
         notifyListeners();
     }

}
  

Комментарии:

1. Джефф, мой поток выполняется в цикле while, и он будет уничтожен кем-то по ошибке. Я хочу знать это и запустить другой поток, как только он будет уничтожен.

2. @джефф, как насчет «try { run(); } finally { notifyListeners(); }»?

3. @pierr, что вы имеете в виду, что он будет уничтожен кем-то по ошибке?

4. @jeff, отложенная копия из моего электронного письма с объяснением: «Пока что мы отменяем все потоки, созданные в группе потоков Xlet. Похоже, это ваш случай, потому что ваш синглтон создается в группе загрузчик классов / поток Xlet.»

5. Это не похоже на то, что кто-то другой бродит по вашему коду и прерывает потоки на вас. Похоже, что они выполняют функции в вашем приложении, которые приводят к уничтожению потоков. Ваша задача как разработчика — создать программу таким образом, чтобы она вызывала нужный вам код при срабатывании этой «ошибочной» функции и / или в первую очередь предотвращала ошибочное завершение.

Ответ №3:

Уничтожен или прерван?

Если вы следите за попыткой прервать ваш поток, самый простой способ сделать это — перехватить InterruptedException . В супер псевдокоде:

 // in my Thread
public void run() {
    try {
        boolean keepRunning = true;
        while (keepRunning) {
            // Do useful work
            // Call other methods
            // As long as they aren't also catching InterruptedException
        }
        System.err.println("Finished running since keepRunning is now false");
    } catch (InterrruptedException ie) {
        // This is where you would put your "onDestroy" functionality
    }
}
  

Ответ №4:

@Jeff прав.

… и он будет уничтожен кем-то по ошибке.

Потоки не становятся «убитыми» или «уничтоженными». Они завершаются в результате действий, которые они предпринимают сами. Существуют два сценария завершения потока:

  • run() Метод возвращает. Обычно это происходит по замыслу; т. е. потому, что метод завершил все, для чего он был разработан.

  • run() Метод генерирует или распространяет исключение. Обычно это происходит в результате какой-либо ошибки в потоке, вызывающей неожиданное непроверенное исключение.

(Я игнорирую возможность того, что какая-то JVM может реализовать устаревший Thread.destroy() метод, и кто-то может быть достаточно сумасшедшим, чтобы вызвать его.)

Это не означает, что мониторинг завершения потока не является полезной вещью. Просто причина завершения потока отличается от того, что вы предполагаете в своем вопросе / комментариях.

Ответ №5:

Возможно, вы могли бы запустить поток в другой группе потоков. Итак, ваш код не будет выполняться в группе потоков Xlet, следовательно, они не смогут завершить поток.