【问题标题】:Java wait for runnable to finishJava等待runnable完成
【发布时间】:2015-10-22 22:49:58
【问题描述】:

我有一个类将启动一个带有无限循环的 Runnable。在某些时候,我想关闭程序,并且我想以一种干净的方式来完成它(例如,确保在执行结束时线程会将一些缓冲区刷新到输出文件等)。我该怎么做?

注意:在 cmets 中我写了 // 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
        }
    }
}

但是shutDown函数的输出总是一样的:

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() 函数,异常就会消失,但输出仍然相同。


编辑:我刚刚注意到,如果我评论 myRunnable.shutdown(); 行并继续使用 myThread.join(); 行,即使我没有停止该线程,我仍然会遇到异常。这是为什么?是因为 Tread 和 Runnable 是两个不同的东西吗?如果是这样,那么我该如何停止 Runnable 并等待其完成?

【问题讨论】:

    标签: java multithreading runnable


    【解决方案1】:

    在“版本 2”中,您正在中断调用 stopParser() 的线程,而不是正在执行 run() 的线程。不要调用Thread.currentThread().interrupt(),而是使用myThread.interrupt()

    我不知道为什么你会在“版本 1”中得到一个 InterruptedException;你一定是在别的地方打电话给Thread.currentThread().interrupt()。只有在检测到当前线程已被另一个线程中断但不能立即终止该线程时,才应该这样做。

    【讨论】:

    • 好的,我明白了。谢谢!我正在中断调用者的线程而不是被调用者的线程。现在,我不再收到异常,但我仍然无法在日志中获得“退出无限循环”字符串,也没有收到“关闭其他内容”。它似乎不再退出无限循环。函数isStopped() 正确吗?该检查是哪个线程,调用者还是被调用者?如何从 runnable 中检查被调用者?
    • PS:我仍然无法摆脱版本2的无限循环,这将是最正确的版本;但不知何故,版本 1 按预期工作,并进行了更正。最好检查一下我的代码。谢谢!我仍然不能很好地理解为什么会发生这种情况,但我接受你的回答。
    • 好的,作为记录,我找到了版本 2 无法正常工作的原因。简而言之,我的无限循环中有一个try{Thread.sleep(time);}catch(InterruptedException e){ ... } 块。于是线程在sleep里面被打断,Exception被抛出并被捕获,无限循环一直在运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多