Java 等待无限循环完成
我有一个在另一个线程上运行的无限while循环。在这个while循环中,我使用了一个字符串。对于这个字符串,我还有一个setter。当有人调用setter时,我希望它等待while循环的当前迭代完成,并将其更改为下一次迭代 这就是我所尝试的: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
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上-一个线程不会自动看到其他线程设置的值。你可以读到很多关于这方面的文章。