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

В приведенном ниже коде у меня есть цикл 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();
            }
        }
    }
}

6 ответов

Решение

Прежде всего, вы не запускаете ни одной темы здесь! Вы должны создать новую ветку и передать свое смущающее имя thread1Runnable к нему:

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 уже предоставляет вам такой встроенный флаг? Дополнительное преимущество прерывает sleeps, делая прерывание потока более отзывчивым.

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

t1.interrupt()

Это приведет к InterruptedException быть брошенным такими методами, как Thread.sleep() или же Object.wait(),

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

РЕДАКТИРОВАТЬ: Теперь я понял, что ваш бесконечный цикл работает в основном потоке, нет никакого потока, созданного вашим кодом, это просто run()нинг Runnable, Вам нужно позвонить Thread.start() в какой-то момент порождает новую тему.

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

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

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

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

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

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

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

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

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


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


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

Другие вопросы по тегам