所以我有一个非常大的项目,但最终将问题归结为以下情况。
我有主类“LoopTest”和另一个类“RandomClassObject”
LoopTest:
public class LoopTest {
static RandomClassObject rco;
public static void main(String[] args) {
rco = new RandomClassObject();
System.out.println("RCO has finished");
}
}
RandomClassObject:
public class RandomClassObject {
JFrame frame = new JFrame();
JButton button = new JButton("Click Me");
boolean created = false;
public RandomClassObject() {
button.addActionListener(this::buttonActionPerformed);
frame.add(button);
frame.setVisible(true);
while (!created) {
//System.out.println("Done"); //This needs to be uncommented to work.
}
System.out.println("It was been Created");
}
public void buttonActionPerformed(ActionEvent evt) {
created = true;
}
所以我希望我的RandomClassObject等到按下按钮。 我有一个布尔“创建”并有一个循环,循环直到所述布尔值更改为真。
在SOUT“Done”注释掉的情况下运行时,我点击按钮但从未得到第二个SOUT“它已被创建”。
当SOUT“Done”取消注释时,我会收到“Done”的垃圾邮件,一旦我点击按钮,我就会收到SOUT“它已被创建。”
我需要帮助理解为什么我必须在我的循环中放置一个SOUT,以便循环使用buttonClick。
很抱歉,如果这是一个明显的错误,感谢您的回复!
答案 0 :(得分:2)
您遇到同步问题。按钮单击发生在事件线程中,并且您的循环(在主线程中运行)永远不会看到它所做的更新。因为您不强制两个线程之间的内存同步,所以机器可以自由地忽略更改。
对System.out.println
的调用具有强制内存同步的副作用,允许主线程查看事件线程所做的更改。
要解决此问题,请将created
设为AtomicBoolean
或将synchronized
关键字添加到complete
方法。
在任何情况下,循环都是实现此结果的不良方法。考虑从按钮上的事件监听器驱动完成逻辑。
你说你需要暂停你的主线程,直到创建角色。一种方法是使用锁存器:
public class Main {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
JFrame frame = new JFrame("Test...");
JButton button = new JButton("Click Me");
button.addActionListener(e -> latch.countDown());
frame.add(button);
frame.pack();
frame.setVisible(true);
// Wait here for the click in the event thread
latch.await();
System.out.println("Clicked!");
frame.dispose();
}
}
调用latch.await()
将阻止您的主线程,直到您的事件线程使用latch.countDown()
释放锁定。