Как вы убиваете поток в Java?

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

14 ответов


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

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


обычно вы этого не делаете..

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

хорошее объяснение того, почему находится в javadoc здесь (java technote link)


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

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

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

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

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

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

public void cancel() { interrupt(); }

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


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

Class Outer {
    public static volatile flag = true;

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

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

}

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


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

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() );

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

  1. нить.stop () остановит поток, если это позволит диспетчер безопасности.
  2. нить.stop() опасен. Сказав это, если вы работаете в среде JEE, и у вас нет контроля над вызываемым кодом, это может быть необходимо.
  3. вы никогда не должны останавливать остановить рабочий поток контейнера. Если вы хотите запустить код, который имеет тенденцию зависать, (осторожно) запустите новый демон нить и контролировать его, убивая при необходимости.
  4. stop () создает новую ошибку ThreadDeath на вызов поток, а затем вызывает эту ошибку для применения к цель нить. Поэтому трассировка стека, как правило, бесполезна.
  5. в JRE 6 stop() проверяет с менеджером безопасности, а затем вызывает stop1 (), который вызывает stop0 (). stop0 () - собственный код.

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

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

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

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


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

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


конечно, есть случай, когда вы используете какой-то не совсем доверенный код. (Я лично этого загруженные скрипты в моей среде Java. Да, есть сигнал тревоги безопасности звонит везде, но это часть приложения.) В этом неудачном случае вы, прежде всего, просто надеетесь, попросив сценаристов уважать какой-то логический сигнал run/don't-run. Ваш единственный достойный отказоустойчивый-вызвать метод stop в потоке если, скажем, он работает дольше, чем некоторый тайм-аут.

но это просто "приличный", а не абсолютный, потому что код может поймать ошибку ThreadDeath (или любое исключение, которое вы явно бросаете), а не переосмыслить его, как предполагается, джентльменский поток. Так, нижняя линия АФАЙЯ нет абсолютной безаварийности.


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

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

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/


Как правило, вы не убиваете, останавливаете или прерываете поток (или проверяете, прерывается ли он ()), но пусть он завершается естественным образом.

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

таким образом, вы корректно убить поток :) .


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

существует два основных правильных решения для прекращения управляемых потоков:

  • использование общего флага volatile
  • использование пары резьбы.прерывание () и поток.прервана() методы.

хорошее и подробное объяснение проблем, связанных с резким прекращением потоков, а также примеры неправильных и правильных решений для прекращения контролируемых потоков можно найти здесь:

https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads


вот несколько хороших чтений по этому вопросу:

Что Вы Делаете С InterruptedException?

выключение потоков чисто


Я не получил прерывание для работы в Android, поэтому я использовал этот метод, отлично работает:

boolean shouldCheckUpdates = true;

private void startupCheckForUpdatesEveryFewSeconds() {
    Thread t = new Thread(new CheckUpdates());
    t.start();
}

private class CheckUpdates implements Runnable{
    public void run() {
        while (shouldCheckUpdates){
            //Thread sleep 3 seconds
            System.out.println("Do your thing here");
        }
    }
}

 public void stop(){
        shouldCheckUpdates = false;
 }