#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, следовательно, они не смогут завершить поток.