Как остановить поток, который работает навсегда без использования

В приведенном ниже коде у меня есть цикл while (true). учитывая ситуацию, когда в блоке try есть какой-то код, где поток должен выполнять некоторые задачи, которые занимают около минуты, но из-за некоторой ожидаемой проблемы он работает навсегда. мы можем остановить этот поток?


public class thread1 implements Runnable {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        thread1 t1 = new thread1();
        t1.run();

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            try{        
                Thread.sleep(10);

            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

Ответ 1

Прежде всего, вы не начинаете нить здесь! Вы должны создать новый поток и передать его смутно названный thread1 Runnable к нему:

thread1 t1 = new thread1();
final Thread thread = new Thread(t1);
thread.start();

Теперь, когда у вас действительно есть поток, есть встроенная функция для прерывания выполнения потоков, называемых... interrupt():

thread.interrupt();

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

while(!Thread.currentThread().isInterrupted()){
    try{        
        Thread.sleep(10);
    }
    catch(InterruptedException e){
        Thread.currentThread().interrupt();
        break; //optional, since the while loop conditional should detect the interrupted state
    }
    catch(Exception e){
        e.printStackTrace();
    }

Две заметки: цикл while теперь заканчивается при потоке isInterrupted(). Но если поток прерывается во время сна, JVM так любезно информирует вас, выбросив InterruptedException из sleep(). Поймайте его и сломайте свою петлю. Что это!


Что касается других предложений:

Устаревшие. Этот метод по своей сути небезопасен [...]

  • Добавление собственного флага и слежение за ним в порядке (просто не забудьте использовать AtomicBoolean или volatile!), но зачем беспокоиться, если JDK уже предоставил вам встроенный флаг? Дополнительным преимуществом является прерывание sleep s, что делает поток прерывания более отзывчивым.

Ответ 2

Правильный способ остановить поток - interrupt it (stop() устарел и может иметь неприятные побочные эффекты):

t1.interrupt()

Это вызовет вызов InterruptedException с помощью таких методов, как Thread.sleep() или Object.wait().

Затем просто добавьте блок catch для этого исключения и просто break из цикла while.

EDIT: теперь я понял, что ваш бесконечный цикл работает в основном потоке, там нет потока, созданного вашим кодом, а просто run() ning a Runnable. Вы должны вызвать Thread.start() в какой-то момент, чтобы создать новый поток.

Ответ 3

Создайте поле boolean keepGoing, которое вы установили в true, перед тем, как начать свой поток, и замените while (true) на while (keepGoing). В какой-то момент вы решаете, где, просто измените значение keepGoing на false, и он выйдет из цикла.

Ответ 4

Единственный способ остановить произвольный поток - это прервать его. Сохраните ссылку на него, затем вызовите метод прерывания.

Ответ 5

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

public void run() {
    try{        
        while(true) {
            Thread.sleep(10);
        }
    } catch(InterruptedException e){
        System.out.println("Thread interrupted"));
    }
}

Ответ 6

Я рекомендую использовать Thread.interrupt() (как упоминалось @Bohemian). Он имеет несколько преимуществ перед использованием специальных флагов:

  • Для этого вам не нужно создавать и использовать API-интерфейс приложения. (И прерывания гарантируются потокобезопасными...)

  • Thread.interrupt() будет прервать потоки, заблокированные в wait() или join или, возможно, 1 некоторые блокирующие вызовы ввода-вывода.

Однако это не волшебная пуля. Если поток, который вы пытаетесь остановить, выполняет обычный код, он должен периодически проверять свой флаг interrupted(), иначе он не остановится. Это оставляет нас так же, как и лодка, когда мы находимся с механизмом ad-hoc flag. Поток должен взаимодействовать, или он не может быть (безопасно) остановлен.

1 - Это мутная область. С одной стороны, есть InterruptedIOException, в котором javadoc говорит "Сигналы о том, что операция ввода-вывода была прервана". С другой стороны, исключение явно не упоминается в javadocs для различных классов потоков java.io.


Правда, какой-то сторонний код может не иметь дело с флагом interrupted, и прерывания могут быть "съедены" в результате. Но вы можете проверить это, если у вас есть исходный код. И ситуация не сильно отличается от стороннего кода, не обращая внимания на ваш механизм флагов ad-hoc.


Я бы НЕ рекомендовал использовать Thread.stop(). Это принципиально чешуйчатый. Некоторые люди утверждают, что он работает для них, но IMO они либо имеют дело со специальным случаем, который работает... или им повезло.