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


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

14 331

14 ответов:

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

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

вообще нет..

вы просите его прервать все, что он делает с помощью нить.прерывание () (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
            }
        }
    }

}

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

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

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

все это, и он может сделать обработку ответа, которая может быть интенсивным процессором. И вы, как разработчик, даже не можете остановить его, потому что вы не можете бросить 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;
 }