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

191
14 апреля 2022, 21:20

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

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

Answer 1

Для завершения потока нужно завести флаг, в методе 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){
            }
        }
    }
}
Answer 2

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

Этот код не работает так как вы ожидаете потому, что метод 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) {
    // нас прервали   
}
Answer 3

Я тоже не люблю наследоваться от 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()) {
        }
    }
}
READ ALSO
Как рисовать на JLabel?

Как рисовать на JLabel?

Создаю программу гитарных аккордов в SwingВ программе реализовал картинку "гитарный гриф" на JLabel следующим образом:

359
Java. Реализация очереди

Java. Реализация очереди

У меня есть код ( не мой ), в котором реализована очередь, с методом добавления и удаления элементовЯ не могу понять, зачем инициализировать...

222
Как умножить EditText на 3 TextView и разделить на 100

Как умножить EditText на 3 TextView и разделить на 100

Я скачал приложение с рецептамиЯ туда хочу добавлять свои рецепты которые проверил, как и на сколько они поднимают сахар

236
Почему при перемножении положительных чисел, получается отрицательное?

Почему при перемножении положительных чисел, получается отрицательное?

При создании, классу Person передается возраст в годах (от 1 до 100)Метод getMilliseconds пересчитывает возраст в миллисекундах

201