Как убить поток, который имеет некоторое время (правда)?
Я пытаюсь закрыть весь поток в моем потоке.
Обычно я стараюсь:
while(!Thread.currentThread().isInterrupted()) {...
Чтобы закрыть цикл while...
Но у меня есть один Thread, который состоит только из
while(!Thread.currentThread().isInterrupted()) {//which is true
Вот как я закрываю потоки:
pool.shutdownNow();
Итак, как бы вы закрыли такой поток?
Ответы
Ответ 1
Вы можете добавить volatile
boolean flag
.
public class Worker implements Runnable {
volatile boolean cancel = false;
@Override
public void run() {
while (!cancel) {
// Do Something here
}
}
public void cancel() {
cancel = true;
}
}
Теперь вы можете просто позвонить
worker.cancel();
Update:
Из документа Java shutdownNow()
Попытка остановить все активное выполнение задач, приостанавливает обработку ожидающих задач и возвращает список задач, ожидающих выполнения.
здесь нет никаких гарантий, кроме лучших попыток прекратить обработку, активно выполняющую задачи. Например, типичные реализации будут отменены с помощью Thread.interrupt(), поэтому любая задача, которая не отвечает на прерывания, может никогда не прерывать.
Таким образом, либо вам нужно будет определить свою политику прерывания, сохранив прерывания
catch (InterruptedException ie) {
// Preserve interrupt status
Thread.currentThread().interrupt();
}
Ответ 2
Вместо этого вы можете использовать сам созданный флаг как условие для цикла while.
public class MyClass implements Runnable
{
private volatile boolean running = true;
public void stopRunning()
{
running = false;
}
public void run()
{
while (running)
{
}
// shutdown stuff here
}
}
Теперь, чтобы остановить его, просто позвоните:
myClassObject.stopRunning();
Это позволит нормальному завершению кода.
Ответ 3
Если вы реализовали это, как вы описали, он должен просто работать.
Когда вы вызываете pool.shutdownNow()
, предполагается прервать все текущие рабочие потоки. Предполагая, что специфичные для приложения методы run()
проверяют прерванный флаг и завершают себя, когда они находят его установленным, ваши потоки должны завершаться.
В действительности нет необходимости добавлять другой механизм, используя флаг ad hoc cancel... или некоторые такие.
Кстати, есть несколько причин, по которым interrupt()
лучше, чем специальная аннулирование:
- Стандартные API, такие как ExecutorService, используют его.
- Различные низкоуровневые API-методы, такие как
sleep
, wait
, join
и некоторые методы ввода-вывода чувствительны к нему.
Ответ 4
Если вы используете реализацию java.util.concurrent
ExecutorService, то он обязательно отправит сигнал interrupt
всем потокам в пуле потоков. Проблема с вашей задачей-изгоем может заключаться в том, что цикл на самом деле не повторяется, а блокирует где-то внутри, поэтому статус interrupted
вообще не проверяется.
Еще одна проблема, которая может возникнуть у вас: цикл while запускает некоторый код, который ловит InterruptedException без правильной обработки, эффективно проглатывание сигнала прерывания. Это обычная ошибка кодирования и в большинстве случаев из-за уродливой правды, которую проверяет InterruptedException
.