Как прервать нужный поток в Java?

Разбираюсь с потоками, написал такой код:

public class main {
    public static void main(String[] args) {
        Horse horsik = new Horse();
        Thread tr1 = new Thread(horsik, "Anna");
        tr1.start();
        horsik.horseStop();
    }
    public static class Horse implements  Runnable{

        public void horseStop(){
            String trName = Thread.currentThread().getName();
            System.out.println(trName);
            Thread.currentThread().interrupt();
        }

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()){
            }
        }
    }
}

Пытаюсь из метода main, через статический метод написанный в классе - остановить поток, но не работает. Объясните пожалуйста почему?


Ответы (3 шт):

Автор решения: Roman Konoval

Начнем с того, что это называется не усыпить, а прервать.

Этот код не работает так как вы ожидаете потому, что метод horseStop вызывается в главном потоке (т.е. потоке который выполняет метод main). А остановить вы хотите другой поток, тот который выполняет метод Horse.run. Поэтому сигнал прерывания посылается не тому потоку, которому вы хотите его послать.

Thread.currentThread() возвращает текущий поток, из которого собственно происходит вызов этой функции. Вам же нужно вызывать interrupt на объекте tr1. Так как ссылка на объект tr1 недоступна внутри horseStop, то придется унаследовать Horse от Thread:

class Horse extends Thread {
    public void horseStop(){
        String trName = this.getName();
        System.out.println(trName);
        this.interrupt();
    }

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){
        }
    }
}

Только учтите, что правильно проверять на прерывание внутри run нужно так:

try {
    // делаем что-то 
} catch (InterruptedException e) {
    // нас прервали   
}
→ Ссылка
Автор решения: Олексій Моренець

Я тоже не люблю наследоваться от Thread, поэтому юзаю такой метод:

public static void main(String[] args) {
    Horse horsik = new Horse();
    horsik.horseStop();
}

public static class Horse implements Runnable {
    Thread t;

    public Horse() {
        this.t = new Thread("Anna");
        this.t.start();
    }

    public void horseStop() {
        String trName = this.t.getName();
        System.out.println(trName);
        this.t.interrupt();
    }

    @Override
    public void run() {
        while (!Thread.interrupted()) {
        }
    }
}
→ Ссылка
Автор решения: Dmitry

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

public class main {
    public static void main(String[] args) {
        Horse horsik = new Horse();
        Thread tr1 = new Thread(horsik, "Anna");
        tr1.start();
        horsik.horseStop();
    }
    public static class Horse implements  Runnable{
        boolean stop = false;
        public void horseStop(){
            String trName = Thread.currentThread().getName();
            System.out.println(trName);
            stop = true;
        }

        @Override
        public void run() {
            while (!stop){
            }
        }
    }
}
→ Ссылка