Как вы убиваете нить в Java? - PullRequest
356 голосов
/ 22 марта 2009

Как убить java.lang.Thread в Java?

Ответы [ 15 ]

179 голосов
/ 22 марта 2009

Смотрите эту ветку от Sun о том, почему они устарели Thread.stop(). Подробно рассказывается о том, почему это был плохой метод, и что нужно сделать для безопасной остановки потоков в целом.

Они рекомендуют использовать общую переменную в качестве флага, который просит фоновый поток остановиться. Затем эта переменная может быть установлена ​​другим объектом, запрашивающим завершение потока.

126 голосов
/ 22 марта 2009

Как правило, вы не ..

Вы просите его прервать все, что он делает, используя Thread.interrupt () (ссылка на Javadoc)

Хорошее объяснение почему в javadoc здесь (ссылка на технику java)

63 голосов
/ 09 июля 2012

В Java потоки не уничтожаются, но остановка потока выполняется кооперативным способом . Поток просят прекратить, и затем поток может корректно завершиться.

Часто используется поле volatile boolean, которое поток периодически проверяет и завершает, когда ему присваивается соответствующее значение.

I не будет использовать boolean, чтобы проверить, должен ли поток завершить . Если вы используете volatile в качестве модификатора поля, это будет работать надежно, но если ваш код становится более сложным, так как вместо этого используются другие методы блокировки внутри цикла while, может случиться, что ваш код не прекратит работу вообще или, по крайней мере, занимает больше времени , как вы можете.

Некоторые методы блокировки библиотеки поддерживают прерывание.

Каждый поток уже имеет логический флаг Прерванный статус , и вы должны использовать его. Это может быть реализовано так:

public void run() {
   try {
      while (!interrupted()) {
         // ...
      }
   } catch (InterruptedException consumed)
      /* Allow thread to exit */
   }
}

public void cancel() { interrupt(); }

Исходный код адаптирован из Параллелизм Java на практике . Поскольку метод cancel() является общедоступным, вы можете позволить другому потоку вызывать этот метод так, как вам нужно.

18 голосов
/ 22 марта 2009

Один из способов - установить переменную класса и использовать ее в качестве стража.

Class Outer {
    public static volatile flag = true;

    Outer() {
        new Test().start();
    }
    class Test extends Thread {

        public void run() {
            while (Outer.flag) {
                //do stuff here
            }
        }
    }

}

Установите внешнюю переменную класса, т.е. flag = true в приведенном выше примере. Установите значение false, чтобы «убить» поток.

11 голосов
/ 23 апреля 2014

Есть способ, как вы можете это сделать. Но если вам пришлось его использовать, либо вы плохой программист, либо вы используете код, написанный плохими программистами. Итак, вы должны подумать о том, чтобы перестать быть плохим программистом или перестать использовать этот плохой код. Это решение предназначено только для ситуаций, в которых НЕТ ДРУГОГО ПУТИ.

Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
8 голосов
/ 25 января 2016

Я хочу добавить несколько наблюдений, основываясь на накопленных комментариях.

  1. Thread.stop () остановит поток, если это разрешит менеджер безопасности.
  2. Thread.stop () опасен. Тем не менее, если вы работаете в среде JEE и не можете контролировать вызываемый код, это может оказаться необходимым.
  3. Никогда не прекращайте останавливать рабочий поток контейнера. Если вы хотите запустить код, который склонен зависать, (осторожно) запустите новый поток демона и следите за ним, убивая при необходимости.
  4. stop () создает новую ошибку ThreadDeath в вызывающем потоке , а затем вызывает эту ошибку для применения к потоку target . Поэтому трассировка стека, как правило, ничего не стоит.
  5. В JRE 6 stop () проверяет диспетчер безопасности и затем вызывает stop1 (), который вызывает stop0 (). stop0 () - это собственный код.
7 голосов
/ 18 февраля 2016

Я бы проголосовал за Thread.stop().

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

Все это, и он может выполнять обработку ответов, которая может сильно загружать процессор. И вы, как разработчик, не можете даже остановить это, потому что вы не можете бросить if (Thread.currentThread().isInterrupted()) строк во всем коде.

Так что невозможность принудительно остановить поток это странно.

5 голосов
/ 05 ноября 2013

Вопрос довольно расплывчатый. Если вы имели в виду «как мне написать программу, чтобы поток прекратил работать, когда я этого захочу», тогда могут пригодиться другие ответы. Но если вы имели в виду «у меня аварийная ситуация с сервером, которую я не могу перезапустить прямо сейчас, и мне просто нужен конкретный поток, чтобы умереть, что бы ни случилось», то вам нужен инструмент вмешательства, соответствующий инструментам мониторинга, таким как jstack.

Для этого я создал jkillthread . Смотрите инструкции по его использованию.

4 голосов
/ 20 февраля 2011

Конечно, есть случай, когда вы запускаете какой-то не полностью доверенный код. (Лично я имею это, позволяя загруженным сценариям выполняться в моей среде Java. Да, повсюду звучит сигнал тревоги, но это часть приложения.) В этом прискорбном случае вы, прежде всего, надеетесь, спрашивая авторов сценариев. уважать какой-то логический сигнал «запустить / не запустить». Единственный достойный отказоустойчивый метод - это вызвать метод stop в потоке, если, скажем, он работает дольше, чем некоторое время ожидания.

Но это просто "прилично", а не абсолютно, потому что код может перехватить ошибку ThreadDeath (или любое другое исключение, которое вы явно выбросили), а не перебрасывать ее, как это должен делать джентльменский поток. Итак, суть в том, что AFAIA не является абсолютной отказоустойчивостью.

3 голосов
/ 20 августа 2014

Нет способа изящно убить поток.

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

public class CancelSupport {
    public static class CommandExecutor implements Runnable {
            private BlockingQueue<String> queue;
            public static final String POISON_PILL  = “stopnow”;
            public CommandExecutor(BlockingQueue<String> queue) {
                    this.queue=queue;
            }
            @Override
            public void run() {
                    boolean stop=false;
                    while(!stop) {
                            try {
                                    String command=queue.take();
                                    if(POISON_PILL.equals(command)) {
                                            stop=true;
                                    } else {
                                            // do command
                                            System.out.println(command);
                                    }
                            } catch (InterruptedException e) {
                                    stop=true;
                            }
                    }
                    System.out.println(“Stopping execution”);
            }

    }

}

BlockingQueue<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);

http://anandsekar.github.io/cancel-support-for-threads/

...