Вопрос

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

Это было полезно?

Решение

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

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

Другие советы

Как правило, вы этого не делаете..

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

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

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

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

Я не стал бы используйте boolean чтобы проверить, должен ли поток прекратить.Если вы используете volatile в качестве модификатора поля это будет работать надежно, но если ваш код станет более сложным, for вместо этого использует другие методы блокировки внутри 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. Thread.stop() остановит поток, если менеджер безопасности разрешит это.
  2. Thread.stop() опасен.Сказав это, если вы работаете в среде JEE и у вас нет контроля над вызываемым кодом, это может быть необходимо.
  3. Вы никогда не должны останавливать рабочий поток контейнера.Если вы хотите запустить код, который имеет тенденцию зависать, (осторожно) запустите новый поток демона и следите за ним, отключая при необходимости.
  4. stop() создает новую ошибку ThreadDeath на зовущий поток, а затем приводит к тому, что эта ошибка применяется к цель Нитки.Таким образом, трассировка стека, как правило, бесполезна.
  5. В JRE 6 функция stop() проверяет с помощью менеджера безопасности, а затем вызывает функцию stop1(), которая вызывает функцию stop0().stop0() - это машинный код.

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

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

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

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

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

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

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

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

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

Вы можете попытаться прервать поток, одна из стратегий 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
  • Использование пары методов Thread.interrupt() и Thread.interrupted().

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

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

Вот пара хороших статей на эту тему:

Что Вы делаете с InterruptedException?

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

"Прерывание потока" - неподходящая фраза для использования.Вот один из способов, которым мы можем реализовать изящное завершение / выход потока по желанию:

Runnable, который я использовал:

class TaskThread implements Runnable {

    boolean shouldStop;

    public TaskThread(boolean shouldStop) {
        this.shouldStop = shouldStop;
    }

    @Override
    public void run() {

        System.out.println("Thread has started");

        while (!shouldStop) {
            // do something
        }

        System.out.println("Thread has ended");

    }

    public void stop() {
        shouldStop = true;
    }

}

Класс запуска:

public class ThreadStop {

    public static void main(String[] args) {

        System.out.println("Start");

        // Start the thread
        TaskThread task = new TaskThread(false);
        Thread t = new Thread(task);
        t.start();

        // Stop the thread
        task.stop();

        System.out.println("End");

    }

}

У меня не получилось заставить прерывание работать в 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;
 }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top