我有以下代码:
import java.util.ArrayList;
public class main {
final static Object lock= new Object();
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
System.out.println("-------");
finish finished = new finish(false);
ArrayList<Boolean> arr = new ArrayList<>();
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getId() + " Is setting");
finished.setFinished(true);
});
t1.start();
synchronized (lock){
if (finished.isFinished == false) {
System.out.println(Thread.currentThread().getId() + " Is adding");
arr.add(new Boolean(finished.isFinished));
} else {
System.out.println("Done");
}
}
System.out.println("The length of array is " + arr.size());
if (arr.size() > 0) {
System.out.println("The val of array is " + arr.get(0));
}
}
}
}
class finish {
public boolean isFinished = false;
public finish(boolean finished) {
this.isFinished = finished;
}
public void setFinished(boolean finished) {
this.isFinished = finished;
}
}
我希望得到以下输出:
数组的长度为1 数组的val是false
要么
完成
大多数时候都是这种情况。但有时输出是:
数组的长度为1 数组的val是真的
这意味着,关键部分中存在上下文切换。我试图在一个对象上同步代码,但它没有帮助。这是一个经典的同步问题,但我无法解决它。也许我应该使用原子对象,但我不知道它们在这种情况下会有什么帮助。或许我对java很苛刻,我不应该在for循环中测试它?我在Linux操作系统上运行此示例。我认为我的同步没有意义。但我不知道如何解决它。
你的示例代码试图做什么并不清楚,但是如果你想等待线程完成,请使用t1.join()
并处理抛出的InterruptedException
。另外,如果您打算在多个线程中使用它,finished
应该是AtomicBoolean
。
但总而言之,代码存在问题,并不反映您尝试处理的任何现实场景。
在此代码中,您正在读取相同的变量两次,这允许它可以更改。最简单的解决方案是只读一次。
boolean isFinished = finished.isFinished;
if (isFinished) {
System.out.println("Done");
} else {
System.out.println(t1 + " Is adding");
arr.add(isFinished);
}