Как я могу убить нить? без использования stop (); - PullRequest
24 голосов
/ 06 мая 2011
Thread currentThread=Thread.currentThread();
        public void run()
        {               

             while(!shutdown)
            {                               
                try
                {
                    System.out.println(currentThread.isAlive());
                Thread.interrupted();

                System.out.println(currentThread.isAlive());
                if(currentThread.isAlive()==false)
                {
                    shutdown=true;
                }
                }
                catch(Exception e)
                {
                    currentThread.interrupt();
                }                   
            }
        }

    });
    thread.start();

Ответы [ 3 ]

56 голосов
/ 06 мая 2011

Альтернативой вызову stop является использование прерывания, чтобы сообщить потоку, что вы хотите, чтобы он завершил свою работу. (Предполагается, что поток, который вы хотите остановить, ведет себя хорошо, если он игнорирует исключения InterruptedException, поедая их сразу после их выброса, и не проверяя состояние прерывания, тогда вы возвращаетесь к использованию stop ().)

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

public class HelloWorld {

    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {

            public void run() {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        Thread.sleep(5000);
                        System.out.println("Hello World!");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.start();
        System.out.println("press enter to quit");
        System.in.read();
        thread.interrupt();
    }
}

О чем нужно знать:

  • Прерывание приводит к немедленному броску sleep() и wait(), в противном случае вы застряли в ожидании, когда пройдет время сна.

  • Обратите внимание, что нет необходимости в отдельном логическом флаге.

  • Остановленный поток взаимодействует, проверяя статус прерывания и перехватывая InterruptedExceptions вне цикла while (используя его для выхода из цикла). Прерывание - это единственное место, где можно использовать исключение для управления потоком, и в этом весь смысл.

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

Несколько замечаний по поводу размещенного кода:

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

  • Проверка того, является ли поток работоспособным, всегда всегда будет приводить к истине (если только нет ошибки, когда переменная экземпляра currentThread ссылается на неправильный поток), Thread#isAlive ложна только после завершения потока выполнение не возвращает false только потому, что оно было прервано.

  • Вызов Thread#interrupted приведет к очистке флага прерывания и здесь не имеет смысла, тем более что возвращаемое значение отбрасывается. Смысл вызова Thread#interrupted состоит в том, чтобы проверить состояние прерванного флага, а затем очистить его, это удобный метод, который используется для вещей, которые выдают InterruptedException.

14 голосов
/ 06 мая 2011

Обычно поток прерывается, когда прерывается . Так почему бы не использовать native boolean ? Попробуйте isInterrupted () :

   Thread t = new Thread(new Runnable(){
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                // do stuff         
            }   
        }});
    t.start();

    // Sleep a second, and then interrupt
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {}
    t.interrupt();
6 голосов
/ 06 мая 2011

Хороший способ сделать это - использовать логический флаг для обозначения потока.

class MyRunnable implements Runnable {

    public volatile boolean stopThread = false;

    public void run() {
            while(!stopThread) {
                    // Thread code here
            }
    }

}

Создайте экземпляр MyRunnable с именем myrunnable, оберните его в новый экземпляр Thread и запустите экземпляр.Если вы хотите пометить поток как остановленный, установите myrunnable.stopThread = true.Таким образом, он не останавливается посреди чего-либо, только там, где мы ожидаем, что он остановится.

...