【问题标题】:Unexpected behavior of Java threadJava 线程的意外行为
【发布时间】:2012-08-29 17:53:29
【问题描述】:

我在回答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 消息。为什么第一次没有显示消息?

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    令人惊讶的是,它可以正常工作并显示 JOptionPane 消息。为什么第一次没有显示消息?

    button_clicked 未标记为volatile,并且正在从与主线程不同的线程进行更新。由于回调是从事件处理程序线程进行的,因此除非将 button_clicked 定义为 volatile boolean,否则主线程不会看到更新。进入睡眠状态可能会跨越内存屏障,幸运的是,button_clicked 会在主线程中更新。

    这里还有更多reading about volatile 以及为什么在我们处理多个线程时它很重要。


    另一个问题是你有一个无限循环,它正在向System.out 发送消息。这会在一段时间后完全阻塞,因为控制台无法快速显示行,这会停止检查点击。

    【讨论】:

    • 更新:我删除了 System.out.println()。即使没有,问题仍然存在。
    • 您能否解释一下-“由于回调是从事件处理程序线程进行的,所以主线程将看不到更新”?据我了解,主要是调用abc类的一个方法,应该总能得到button_clicked的最新值。
    • 但是我们讨论的是可以在多个处理器上运行的多个线程,每个线程都有自己的内存缓存。 Java 需要被告知button_clicked 需要在线程之间同步。这里有一些阅读:javamex.com/tutorials/synchronization_volatile.shtml
    • 太棒了!感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 2011-10-06
    相关资源
    最近更新 更多