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

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

Ответ 1

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

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

Ответ 3

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

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

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

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

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

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

public void cancel() { interrupt(); }

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

Ответ 4

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

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, чтобы "убить" поток.

Ответ 5

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

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

Ответ 6

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

  • Thread.stop() остановит поток, если это разрешит менеджер безопасности.
  • Thread.stop() является опасным. Сказав это, если вы работаете в среде JEE, и у вас нет контроля над вызываемым кодом, это может быть необходимо.
  • Вы никогда не должны останавливать поток рабочего контейнера. Если вы хотите запустить код, который имеет тенденцию зависать, (осторожно) запустите новый поток демона и проверите его, при необходимости, убив.
  • stop() создает новую ThreadDeath-ошибку в вызывающем потоке, а затем приводит к тому, что Ошибка применяется к целевому потоку. Следовательно, трассировка стека вообще бесполезна.
  • В JRE 6 stop() проверяет с помощью менеджера безопасности, а затем вызывает stop1(), который вызывает stop0(). stop0() - это собственный код.

Ответ 7

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

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

Невозможно изящно убить поток.

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

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/

Ответ 11

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

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

Таким образом вы грациозно убиваете нить :).

Ответ 12

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

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

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

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

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

Ответ 14

Я не получил прерывание для работы на 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;
 }