我在回答this question时遇到了这种有趣的情况。
尝试这段设计糟糕的代码 -
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class abc extends JFrame implements ActionListener
{
boolean button_clicked = false;
JButton b1;
abc(){
this.setSize (400, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.createUI();
}
void createUI(){
this.setLayout(null);
b1 = new JButton("Click here");
b1.setSize(110,30);
b1.setLocation(10,210);
this.add(b1);
b1.addActionListener(this);
}
public boolean isButton_clicked()
{
return button_clicked;
}
public void setButton_clicked(boolean button_clicked) {
this.button_clicked = button_clicked;
}
public void actionPerformed(ActionEvent arg0) {
button_clicked = true;
}
}
这是主要方法。
class tempMain extends JFrame
{
public static void main(String[] args) throws Exception
{
abc temp = new abc();
temp.setVisible(true);
while(true)
{
// Thread.sleep(200);
if(temp.isButton_clicked())
{
JOptionPane.showMessageDialog(null, "Hello");
temp.setButton_clicked(false);
}
}
}
}
当我在我的Windows 7机器上运行它时,在我点击按钮后,至少大约一分钟没有发生任何事情(我没有等到那之后)。
现在,只做一个小改动 -
Thread.sleep(200); // uncomment this from the main.
令人惊讶的是,它可以工作并显示一条JOptionPane消息。为什么第一次不显示消息?
答案 0 :(得分:2)
令人惊讶的是,它可以工作并显示一条JOptionPane消息。为什么第一次不显示消息?
button_clicked
未标记为volatile
,并且正在从与主线程不同的线程更新。由于回调是从事件处理程序线程进行的,因此除非将button_clicked
定义为volatile boolean
,否则主线程将看不到更新。进入睡眠状态可以允许跨越内存屏障,并且幸运地在主线程中更新button_clicked
。
这里还有一些reading about volatile以及为什么在我们处理多个线程时它很重要。
另一个问题是你有一个无限循环,它向System.out
发送消息。这会在一段时间后完全阻塞,因为控制台无法显示快速停止检查点击的行。