在另一个线程中更改while循环条件,没有任何反应?

时间:2015-10-15 18:36:32

标签: java multithreading loops while-loop

所以,前几天我做了一个分形绘图程序,当它变得太慢时,我想我会通过多线程来加快它的速度。所以我介绍了几个线程,每个线程绘制一部分图像。要知道我何时完成了线程,我引入了两个变量AMOUNT_OF_THREADSthreadsDone。我创建了AMOUNT_OF_THREADS个线程,每个线程都绘制了自己的分区,并在完成后增加threadsDone。在主要方法中,我放入

while (threadsDone < AMOUNT_OF_THREADS)
    ;

令我惊讶的是,循环从未完成循环。我知道它,因为每个线程打印出"Thread done",当主方法循环完成时,它应该打印出"Main done"但它没有。我试图打印threadsDone < AMOUNT_OF_THREADS,现在循环停止了。怪异。

我做了一些进一步的测试,这个问题似乎只发生在线程运行> 2ms或每次循环时循环花费> 2ms时才会发生。有时,当线程运行2ms时会发生此错误。

我怀疑打印功能使循环运行时间> 2毫秒,这使我在打印出值时起作用,但我仍然想知道为什么会这样。

所以我的问题是,为什么会发生这种情况?它是编译器/ JVM中的错误还是其他任何错误?我问我的父亲,他在思考了几分钟之后回复说它必须是while循环运行得太快,但他不确定。

以下是一些存在此问题的代码示例:

public class WhileThread {

    public static boolean threadDone = false;

    public static void main(String[] args) {

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                threadDone = true;

                System.out.println("Thread done.");
            }
        }).start();


        while (!threadDone) {

        }


        System.out.println("Main program done.");
    }

}

当您将Thread.sleep中的0更改为10时,此错误永远不会发生。

如果重要,我使用带有Java SE 8的Macbook Air。

1 个答案:

答案 0 :(得分:1)

  

所以我的问题是,为什么会发生这种情况?它是编译器/ JVM中的错误还是其他任何错误?

这不是一个错误,它是一个刻意的设计决定。为了使这样的代码可靠地运行,JVM必须假设任何线程都可以随时更改任何变量,除非它们能够证明这不可能发生。这会抑制各种非常有价值的优化,并使Java代码运行得慢得多。

相反,明确允许这些优化,并添加了几个方法(volatilesynchronized等),以允许编码器显示变量可以由其他线程更改其值的位置。 / p>