在主线程中通过单独的方法更改条件后,单独线程中的循环继续运行

时间:2016-04-03 18:02:31

标签: java multithreading

public void taskInProgress(String jobMessage) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                runningTask = true;
                Test:
                while (runningTask) {
                    for (int i = 0; i < runningStars.length; i++) {
                        System.out.print(runningStars[i].concat(" ").concat(jobMessage));
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        });
        t.start();
    }

    public void taskFinnished(String msg) {
        this.runningTask = false;
        System.out.println("\r".concat(ok(msg)));
    }

希望的效果是,星星在控制台中打印为无限进度条,即嵌套在for循环中的while循环,当我调用方法时,星星得到替换为状态和消息,他们被停止。我通过锁定runningTask中的类字段taskFinnished()来实现此目的。

我的问题是,即使在打破while循环后,星星仍会打印到控制台。即使在while循环条件返回false之后,循环仍继续执行,持续几秒钟。

截图:

enter image description here

如此处所示,在调用Extracting tar archive方法并且while循环中断后,它仍然显示taskFinnished()

以下是使用这些实现的代码:

            tc.taskInProgress("Extracting tar archive");

            // do long operation on main thread, keep console animation running in seperate thread, and return exit int, Unix style

            if (exit == 0) {
                tc.taskFinnished("Tar finished without errors");
           // This breaks the while loop, but more stuff gets printed even after breaking loop
            } else {
                // failed, handle it
            }

2 个答案:

答案 0 :(得分:1)

尝试替换

for (int i = 0; i < runningStars.length; i++)

for (int i = 0; i < runningStars.length && runningTask; i++)

答案 1 :(得分:0)

您的布尔标志(runningTask)必须声明为volatile。否则,无法保证正在运行的线程看到主线程所做的更改。

另一种方法是使用AtomicBoolean。但更好的是,你应该使用已经存在的机制来要求线程停止运行:中断线程(通过调用它上面的interrupt())。正在运行的线程必须使用Thread.currentThread().isInterrupted()定期检查当前线程是否已被中断。

这种机制优于自定义布尔标志的优点是,正在运行的线程被阻塞等待或休眠,它将立即通过抛出InterruptedException而退出其等待/休眠状态。

你应该抓住那个例外,但不要像你一样忽略它,而应该尽快停止运行。