Ява ждать для Runnable, чтобы закончить


У меня есть класс, который будет запускать Runnable с бесконечным циклом. В какой-то момент я хочу завершить работу программы, и я хочу сделать это чистым способом (например, убедиться, что в конце выполнения поток очистит некоторый буфер для вывода файла и т. д.). Как я могу это сделать?

Примечание: в комментариях я написал // Version 1 и // Version 2. Это потому, что я попробовал обе версии, и ни одна из них не работала, я продолжаю получать InterruptedException.

Основной Класс:

public class MainClass {

    private static Thread myThread;
    private static MyRunnable myRunnable;
    private static Logger logger;

    public static void main( String[] args ) {
        ...
        myRunnable = new MyRunnable(logger);
        myThread = new Thread(myRunnable);
        myThread.start();
        ...
    }

    private static void shutDown() {
        logger.debug("Shut down everything.");
        if(myRunnable != null){
            myRunnable.shutdown();
            try {
                myThread.join();
                logger.debug("Runnable Stopped");
            } catch (InterruptedException e) { // Always failing here
                e.printStackTrace();
            }
        }
        // Now stop logger and other things
        logger.debug("Shutdown other stuff");
        ...
        logger.debug("Shutdown logger");
        Configurator.shutdown((LoggerContext)LogManager.getContext());
        System.out.println("Done");
    }
}

Управляемый класс:

public class MyRunnable implements Runnable {

    private AtomicBoolean stop = new AtomicBoolean(false); // Version 1

    public boolean isStopped() { 
        return stop.get(); // Version 1
        return Thread.currentThread().isInterrupted(); // Version 2
    }

    public void shutdown() {
        logger.debug("Stopping my runnable");
        stop.set(true); // Version 1
        Thread.currentThread().interrupt(); // Version 2
    }

    @Override
    public void run() {
        try{
            while(!isStopped()) {
                // Do things
            }
            logger.debug("Exiting from infinite loop");
        } catch(Exception e){
            logger.error("Exception! " + e.getMessage());
        } finally {
            logger.debug("Entering in finally part");
            // Flush buffer, commit to database, ... close stuff
        }
    }
}

Но вывод функции выключения всегда один и тот же:

Shut down everything.
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Thread.join(Thread.java:1260)
    at java.lang.Thread.join(Thread.java:1334)
    at com.my.packageName.MainClass.shutDown(MainClass.java:374)
Shutdown other stuff
Shutdown logger
Done

Если я удаляю функцию join (), исключение исчезает, но вывод остается тем же самым.


EDIT: я только что заметил, что если я комментирую строку myRunnable.shutdown(); и продолжаю линию myThread.join();, я все равно получаю исключение, даже если я не останавливаю этот поток. Почему это так? Не потому ли, что беговая дорожка и беговая дорожка-это две разные вещи? Если это так, то как я могу остановить бегучего и ждать его завершения?

1 2

1 ответ:

В "версии 2" вы прерываете поток, который вызывает stopParser(), а не поток, который выполняет run(). Вместо вызова Thread.currentThread().interrupt() Используйте myThread.interrupt().

Я не знаю, почему вы получили бы InterruptedException в "версии 1"; Вы, должно быть, вызываете Thread.currentThread().interrupt() где-то еще. Вы должны сделать это только тогда, когда вы обнаружили, что текущий поток был прерван другим потоком, но вы не можете завершить поток немедленно.