时钟线程 - 怪异的bug system.out.println

时间:2017-05-23 10:00:41

标签: java multithreading swing listeners

我有我的主题

this.clock = new JLabel();
clockThread = new Thread(new Runnable() {
      public void run() {
            clockRun();
        }
    });
clockThread.start();
this.clock.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (clockDisplayRealTime) {
                clockDisplayRealTime = false;
            } else {
                clockDisplayRealTime = true;
            }
        }

    });

然后这将无法工作,除非我有如下的System.out.println 我正在摸不着头脑,找出问题所在。请帮我。感谢。

public void clockRun() {
        while (true) {
            System.out.println(clockDisplayRealTime);
            if (clockDisplayRealTime) {
                Date date = new Date();
                clockRealtime = date.getTime();
                this.clock.setText(sdf.format(clockRealtime));
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

需要易变性

volatile private boolean clockDisplayRealTime = false;

这个问题是重复的

答案 1 :(得分:0)

Swing组件只应在Event Dispatch Thread上进行变异。

解决问题的最简单方法可能是SwingWorker。您也可以手动完成以下操作:

clockThread = new Thread(() -> {
    while (true) {
        if (clockDisplayRealTime) {
            SwingUtilities.invokeAndWait(() -> {
                Date date = new Date();
                clockRealtime = date.getTime();
                this.clock.setText(sdf.format(clockRealtime));
            });
            Thread.sleep(1000); // no need to update the UI more often than that
        }
    }
});    

您的代码失败的原因是多个线程在没有同步的情况下访问了同一个字段,在这种情况下,Java内存模型不保证一个线程所做的更改对另一个线程可见。通过将访问clockDisplayRealTime字段的所有代码放入同一个线程,您可以巧妙地回避这个问题。