Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 等待无限循环完成_Java_Multithreading_Asynchronous_Synchronization - Fatal编程技术网

Java 等待无限循环完成

Java 等待无限循环完成,java,multithreading,asynchronous,synchronization,Java,Multithreading,Asynchronous,Synchronization,我有一个在另一个线程上运行的无限while循环。在这个while循环中,我使用了一个字符串。对于这个字符串,我还有一个setter。当有人调用setter时,我希望它等待while循环的当前迭代完成,并将其更改为下一次迭代 这就是我所尝试的: import java.util.concurrent.TimeUnit; public class Test { private String testString = "aaaaaaa"; private Te

我有一个在另一个线程上运行的无限while循环。在这个while循环中,我使用了一个字符串。对于这个字符串,我还有一个setter。当有人调用setter时,我希望它等待while循环的当前迭代完成,并将其更改为下一次迭代

这就是我所尝试的:

import java.util.concurrent.TimeUnit;

public class Test {

    private String testString = "aaaaaaa";

    private Test() {
        new Thread(() -> {
            while (true) {
                synchronized (testString) {
                    System.out.println(testString);

                    // Simulating a thread blocking operation
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException exception) {
                        exception.printStackTrace();
                    }

                    System.out.println(testString);
                }
            }
        }).start();
    }

    private void setTestString(String testString) {
        synchronized (testString) {
            this.testString = testString;
        }
    }

    public static void main(String[] args) {
        Test test = new Test();

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }

        test.setTestString("bbbbbbbb");
    }
}
预期产出:

aaaaaaa
aaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
...
实际产量:

aaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
...

为什么
setTestString
方法没有等待?我做错了什么?

问题是线程每次都在读取更新的实例变量。如果希望循环的迭代看到一致的值,那么应该只读取实例变量的值一次。此外,由于您是从一个线程写入它,然后从另一个线程读取它,因此需要使其易失性,或者在同步方法中执行读写操作

private volatile String testString = "aaaaaaa";

private Test() {
    new Thread(() -> {
        while (true) {
                // volatile read
                String localTestString = testString;

                System.out.println(localTestString);

                // Simulating a thread blocking operation
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException exception) {
                    exception.printStackTrace();
                }

                System.out.println(localTestString);
        }
    }).start();
}
当有人调用setter时,我希望它等待while循环的当前迭代完成

这不是一个好的解决办法。如果让set方法等待,则不能保证它在循环的当前迭代完成后得到调度。您可以自己查看:将set方法更改为

private void setTestString(String testString) {
    synchronized (this.testString) {
        this.testString = testString;
    }
}

在方法
setTestString
Thread
中,在这两个位置,您都试图获得从调用位置发送的字符串文本锁。因此,如果您希望这样做,它们实际上不是同一个字符串对象上的锁。你能往那个方向看吗?谢谢,行了!我在没有使
testString
易失性的情况下尝试了它,它仍然可以工作。我想问题是t在这种情况下是不可靠的?或者为什么它需要易变性?没有易变性,它是不可靠的。想象一下,主线程和无限循环被安排在具有单独缓存的不同CPU上-一个线程不会自动看到其他线程设置的值。你可以读到很多关于这方面的文章。