Ответ 1
Это опасная идея. Javadoc для Thread.stop()
объясняет:
Этот метод по своей сути является небезопасным. Остановка потока с помощью Thread.stop заставляет его разблокировать все мониторы, которые он заблокировал (как естественное следствие неконтролируемого исключения ThreadDeath, распространяющегося по стеку). Если какой-либо из объектов, ранее защищенных этими мониторами, находился в противоречивом состоянии, поврежденные объекты становятся видимыми для других потоков, что может привести к произвольному поведению. Многие применения stop должны быть заменены кодом, который просто изменяет некоторую переменную, чтобы указать, что целевой поток должен прекратить работу. Целевой поток должен регулярно проверять эту переменную и возвращаться из метода запуска упорядоченным способом, если переменная указывает, что она должна прекратиться. Если целевой поток ожидает длительные периоды (например, для переменной условия), для прерывания ожидания следует использовать метод прерывания.
По сути, потоки должны быть построены и спроектированы таким образом, чтобы безопасно завершать работу, невозможно безопасно убить произвольные потоки. Достаточно стандартный шаблон реализуется так:
public abstract class StoppableRunnable implements Runnable {
private volatile boolean stopWork;;
private boolean done;
public final void run() {
setup();
while(!stopWork && !done) {
doUnitOfWork();
}
cleanup();
}
/**
* Safely instructs this thread to stop working,
* letting it finish it current unit of work,
* then doing any necessary cleanup and terminating
* the thread. Notice that this does not guarentee
* the thread will stop, as doUnitOfWork() could
* block if not properly implemented.
*/
public void stop() {
stopWork = true;
}
protected void done() {
done = true;
}
protected void setup() { }
protected void cleanup() { }
/**
* Does as small a unit of work as can be defined
* for this thread. Once there is no more work to
* be done, done() should be called.
*/
protected abstract void doUnitOfWork();
}
Вы подразумеваете, что вы не являетесь автором этих потоков, которые предполагают, что они не могут быть безопасно остановлены. В таком случае вы можете вызвать Thread.interrupt()
, чтобы указать потоку остановить его выполнение (вместо описанного выше шаблона вы можете использовать Thread.interrupt()
к аналогичному эффекту), однако аналогичным образом, если разработчик нитей не написал его для обработки прерываний, это может ничего не делать или вызвать несогласованные состояния или другие ошибки.
В конечном итоге Thread.stop()
- это то, что вам нужно, если вы просто хотите "[принудительно] поток прекратить выполнение" и не можете изменить реализацию потока; однако, как использование kill
в Unix, это опасное предложение, и вы должны по существу считать, что ваш JVM находится в неустойчивом и непоправимом состоянии после завершения потока таким образом и пытается выйти из программы как можно быстрее после этого.
Что касается вашего предложения прерывания, то остановка:
Здесь все еще много проблем, в частности, прерывание не гарантирует, что поток будет прерываться немедленно (он работает аналогично, хотя и менее явно, для моего StoppableRunnable
выше) и вместо этого устанавливает флаг, который поток должен прерывать, когда возможное. Это означает, что вы могли бы вызвать Thread.interrupt()
, поток мог бы запустить его надлежащее поведение обработки прерываний, а затем на полпути через него, ваш вызов Thread.stop()
срабатывает, яростно убивая поток и потенциально нарушая вашу JVM. Вызовы Thread.interrupt()
не дают никаких гарантий относительно того, когда или как поток будет реагировать на это прерывание, поэтому я предпочитаю явное поведение в StoppableRunnable
. Излишне говорить, что если вы когда-нибудь назовете Thread.stop()
, то немного выиграйте, сначала позвонив Thread.interrupt()
. Я не рекомендую его, но вы можете просто вызвать Thread.stop()
в первую очередь.
Кроме того, признайте, что код, запускающий ваш цикл, сам по себе в потоке - это означает, что ваш цикл может очень хорошо убить себя первым, оставив все остальные потоки.