Как прервать/остановить поток в Java?

Я пытаюсь остановить поток, но я не могу этого сделать:

public class Middleware {

public void read() {
    try {
        socket = new Socket("192.168.1.8", 2001);

        // code .. 

        Scan scan = new Scan();
        thread = new Thread(scan);
        thread.start();

    } catch (UnknownHostException ex) {
        ex.printStackTrace();

    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

class Scan extends Thread {

    public void run() {

        while (true) {
            try {
            // my code goes here

            } catch (IOException ex) {
                thread.currentThread().interrupt();
            }
        }
    }
}

public void stop() {
    Thread.currentThread().interrupt();
}

// get and setters
}

Поэтому, даже когда я вызываю метод stop, поток не останавливается. Это поддерживает жизнь.

Как я могу прервать/остановить эту тему?

ОБНОВЛЕНИЕ (@маленький подход)

private void tb_startActionPerformed(java.awt.event.ActionEvent evt) {                                         
    Middleware middleware = new Middleware();

    if (tb_start.getText().equals("Start")){
        tb_start.setText("Stop");

        // starting to read rfid tags
        middleware.read();
    }else{
        tb_start.setText("Start");

        // stop reading rfid tags
        middleware.stop();
    }
}

Класс Middleware:

public class Middleware {

    private Scan scan;

    public void read() {

        scan = new Scan();
        scan.start();
    }

    private class Scan extends Thread {

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("reading...");
            }
        }
    }

    public void stop() {
        if (scan != null) {
            scan.interrupt();
        }
    }
}

Но когда я пытаюсь остановить поток, это не так.

Что может быть не так в коде выше?

Ответ 1

Нет причин, по которым вам нужно использовать флаг volatile. Вместо этого просто запросите поток для его состояния с помощью isInterrupted(). Кроме того, почему вы обертываете свой объект потока Scan в другой объект потока? Это кажется мне совершенно ненужным.

Вот что вы должны делать

public class Middleware {
    private Scan scan;

    public void read() {
        try {
            // do stuff

            scan = new Scan();
            scan.start();
        } catch (UnknownHostException ex) {
            // handle exception
        } catch (IOException ex) {
            // handle exception
        }
    }

    private class Scan extends Thread {

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    // my code goes here
                } catch (IOException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    public void stop() {
        if(scan != null){
            scan.interrupt();
        }
    }
}

Вот пример . Кроме того, я бы не рекомендовал расширять Thread.

Ответ 2

Просто return; от вашего времени, и поток умрет, нет необходимости вызывать stop() или прерывание(). Если вы хотите сделать это извне, используйте этот шаблон и вызовите requestStop().

class Scan extends Thread {
    private volatile stop = false;
    public void run() {

        while (!stop) {
            try {
            // my code goes here

            } catch (IOException ex) {
                stop = true;
            }
        }
    }

    public void requestStop() {
        stop = true;
    }

}

Ответ 3

"Многие виды использования stop() должны быть заменены кодом, который просто модифицирует некоторую переменную, указывая на то, что целевой поток должен прекратиться." - java.lang.Thread

Ответ 4

если вы хотите прервать работающий поток, вам нужен доступ к объекту потока.

thread = new Thread(scan);
thread.start();

тогда скажи

thread.interrupt();

это прервет работающий поток.

Ответ 5

Обычный способ остановить поток - иметь флаг volatile, а затем проверить его в методе run. то есть.

class Scan extends Thread {
    volatile stop = false;
    public void run() {

        while (!stop) {
            try {
            // my code goes here

            } catch (IOException ex) {
                thread.currentThread().interrupt();
            }
        }
    }

    public void stop(){
        stop = true;
    }
}

Затем вы можете вызвать scan.stop().

Ответ 6

Полностью согласен с Jim.. Просто добавьте Если ваш поток заблокирован внутри блока try например, чтение на потоке данных и т.д., затем прерывать поток, а также закрыть поток. В обоих случаях поток должен быть пробужден снова, и тогда он сможет увидеть изменение значения "stop" boolean и умереть естественным путем, выпадая из метода run. По крайней мере, это то, что я сделал, чтобы убить мои потоки в потоке shutdown для моего сервера.

Ответ 7

    public void run()
    { 
         while (!Thread.currentThread().isInterrupted()) 
         {
        //do something here
        if(condition)
       {
           Thread.currentThread().interrupt();
       }
   }

Ответ 8

Вместо использования Thread.stop() или Thread.interrupt() вы можете использовать внешние блокировки. В основном, когда вы пытаетесь использовать встроенную блокировку большую часть времени, любое прерывание, которое вы выполняете в потоке, не поддается контролю.

Блокировка повторного входа предоставляет вам методы, указанные ниже.

lock() 
unlock() 
tryLock() 
lockInterruptibly() 
isHeldByCurrentThread() 
getHoldCount() 

Проверьте приведенный ниже пример

final ReentrantLock reentrantLock = new ReentrantLock();    
    @Override
    public void performTask() {
        reentrantLock.lock();
        try { 
             System.out.println(Thread.currentThread().getName() + ": Lock acquired.");
             System.out.println("Processing...");
             Thread.sleep(2000);
        } catch (InterruptedException e) {
             e.printStackTrace();
        } finally {
             System.out.println(Thread.currentThread().getName() + ": Lock released.");
         reentrantLock.unlock();
            }
    }

Это делает ваш код элегантным и лучше обрабатывает прерывание.