2011-12-23 4 views
9

При возникновении определенного таймаута мне нужно убить/отменить/прервать/пропустить текущий поток. Я использую ExecutorService для управления пулом потоков, через который я могу отменить задачу, используя метод cancel(), который удаляет это из представления ExecutorService, но сам поток продолжает работать.Прерывание/Убивание текущей нити

Оглядываясь в сети, люди talk about interrupting threads, которые имеют цикл с использованием метода isInterrupted() или ждут IO, которые могут обрабатываться путем всплытия InterruptedException.

Какова общая практика по уничтожению нитей, которые не имеют ни петли (или имеют какие-либо другие крючки), так и не ждут ввода-вывода? Оглядываясь, Thread.stop(), кажется, делает то, что мне нужно (просто слепо убить поток), но не рекомендуется использовать его.

+1

«Слепо убить нить» - это то, что вы не должны делать никогда. – Viruzzo

+0

Thread.stop() подходит только для тривиальных фрагментов кода, где вы можете понять последствия остановки на каждой возможной линии. Этот тип кода также просто добавить строки для проверки прерванного флага. т. е. не является идеальным решением даже в теории. –

ответ

3

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

Обратите внимание, что потоки в ExecutorService являются циклическими, их цикл включает в себя ожидание того, что задача будет доступна в очереди задач.

Там нет простого среднего в Java, чтобы остановить поток, который не зацикливание, что вы можете сделать, это:

  • Есть летучий булево флаг, что нить в Runnable проверяет время от чтобы увидеть, если он должен остановиться (тот же флаг, который может использоваться как условие в контуре потока).
  • Вызов Thread.interrupt() попробовать (максимум усилий, довольно небезопасно, если вы не знаете, что вы делаете) остановить синхронизацию связанных ожидания/блокировки/aquire/... нить застрял в.
1

I лично порекомендует вам пойти на прерывание маршрута, так как это самый чистый способ и изящный способ закончить этот поток.

Давайте попробуем точно определить нашу цель. Нить - это не что иное, как отдельный процесс, который будет выполнять набор задач, которые вы ему назначили. Вероятно, вам нужно будет найти прерывистые точки в вашем коде и выполнить эти прерывания(). Очевидно, что эти точки должны были прийти к логическому завершению.

Например,

public void run(){ 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicA start 
     //LogicA end 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicB start 
     //LogicB end 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicLong start 
     //Long code here cannot end or exit or kill the thread now. Let it finish 
     //LogicLong ends 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicD start 
     //LogicD end 
} 
+0

Используйте Thread.interrupted() с осторожностью: он перезапускает статус прерывания потока, и многие классы в Java API используют его, что приводит к тому, что прерывание не замечено на уровне нити. – Guillaume

+0

Не совсем. Предоставляя больше контекста, поток создает экземпляр класса через интерфейс и вызывает определенные методы класса. Реализация методов определяется пользователями моей системы, и я ожидаю таких дефектов, как бесконечные циклы. Я хочу избежать этого, убив задания, которые превышают тайм-аут. – nija

+0

@NiranjanJayakar: В этом случае, вероятно, проверка прерывания должна быть проверена в начале этого бесконечного цикла. – bragboy

1

Если вы alread имеют Executorservice то вы получили Future уже. Единственный нормальный и чистый способ отменить работу поэтому вызывает future.cancel(boolean mayInterruptIfRunning). Параметр mayInterruptIfRunning прервет задания, если он работает в данный момент, и ничего не делает, если задание не запущено. Таким образом, вам нужно только написать работу таким образом, чтобы соблюдать прерывание, проверяя Thread.interrupted() время от времени.

Обратите внимание на разницу между вакансии и нить. Вы отправляете задание, и поэтому вам не следует сбрасывать нитью, пытаясь обойти ExecutorService, что совсем не удивляет. Вызывая Future.cancel(true), вы даете всем участвующим сторонам чистый сигнал, что делать.

+0

Согласовано. Но я хочу эквивалент комбинации SIGTERM/SIGKILL для потока. Я недоволен тем, что у меня бесконечные рабочие или дефектные работы, которые могут быть дорогими для моей системы. – nija

Смежные вопросы