为什么我的循环只在使用SOUT时才会继续?

时间:2017-05-16 00:35:42

标签: java netbeans

所以我有一个非常大的项目,但最终将问题归结为以下情况。

我有主类“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。

很抱歉,如果这是一个明显的错误,感谢您的回复!

1 个答案:

答案 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()释放锁定。