2

I came across this interesting situation while answering this question.

Try this piece of poorly designed code -

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;
}

}

Here's the main method.

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);
        }
    }
}
}

When I ran this on my Windows 7 machine, nothing happened for at least about a minute (I didn't wait after that) after I clicked the button.

Now, just make one small change -

  Thread.sleep(200); // uncomment this from the main.

And surprisingly, it works and a JOptionPane message is displayed. Why is the message not displayed the first time?

Community
  • 1
  • 1
CodeBlue
  • 14,631
  • 33
  • 94
  • 132

1 Answers1

2

And surprisingly, it works and a JOptionPane message is displayed. Why is the message not displayed the first time?

button_clicked is not marked as volatile and is being updated from a different thread than the main thread. Since the call-back is made from the event handler thread, the main thread will not see the update unless button_clicked is defined as a volatile boolean. Putting a sleep may allow a memory barrier to be crossed and button_clicked to be updated in the main thread luckily.

Here's some more reading about volatile and why it is important when we are dealing with multiple threads.


Another issue is that you have an infinite loop which is spewing messages to System.out. This completely blocks after a while because the console can't display lines that fast which stops the checking for the click.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • Update : I removed the System.out.println(). The problem persists even without that. – CodeBlue Aug 29 '12 at 18:01
  • Could you please explain - " Since the call-back is made from the event handler thread, the main thread will not see the update" ? As far as I understand, the main is calling a method of the abc class and should always be able to get the latest value of button_clicked. – CodeBlue Aug 29 '12 at 18:11
  • 1
    But we are talking about multiple threads that can be running on multiple processors, each with their own memory caches. Java needs to be told that `button_clicked` needs to be synchronized between the threads. Here's some reading: http://www.javamex.com/tutorials/synchronization_volatile.shtml – Gray Aug 29 '12 at 18:15