Zexdur
Zexdur

Reputation: 31

Java code doesn't work without a println

Here is my code:

while(monster.curHp > 0)
{
    System.out.println("");
    if(battle.pressedButton)
    {
        text = Player.name + ": " + Player.curHitPoints + "     " + monster.name + ": " + monster.curHp;
        battle = new GUIForBattle(text,Player,monster);
    }
}

The weird thing is that if I have that println line in the while loop the code will work normally and when the button is pressed we will update text to have the current status and we will redraw the GUI using the GUIForBattle class, however if I don't have that println it wont redraw. Any advice? Thank you!

Here is the GUIForBattle for more context

public class GUIForBattle extends JFrame {
boolean pressedButton = false;
public GUIForBattle(String words, player PlayerOne, Monster monster)
{
    JFrame frame = new JFrame(); //frame that holds everything
    JPanel Panel = new JPanel(new GridLayout(5,5)); //panel where things get added
    JLabel text = new JLabel(words); // text label
    JButton attack = new JButton("Attack"); //makes a button used to attack
    //adding what pressing the attack button would do 
    attack.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    int attackAmount = PlayerOne.weaponEquipped.att;
                    monster.curHp = monster.curHp - attackAmount;
                    pressedButton = true;
                }
            }
            );
    JButton Item = new JButton("Item"); // makes a button used to use items
    Item.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    //we need to make a item interface
                }
            });
    Panel.add(text); //adds the text to the panel
    Panel.add(attack);
    Panel.add(Item);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 800); //setting size of frame
    frame.add(Panel); //adding the panel to frame
    frame.setVisible(true); //making the frame visible
}

}

Upvotes: 0

Views: 202

Answers (1)

Joeri Hendrickx
Joeri Hendrickx

Reputation: 17445

Your code is inherently multi-threaded; one thread is running through that little while loop; the other is the swing application thread that will be handling your swing event handlers.

If you use shared variables like this (both threads access pressedButton) you need to make sure that variable is synchronized between threads. There are several ways of handling this, but an easy way for this particular problem would be to make the variable volatile.

If the variable is not synchronized in any way, there is no guarantee by the JVM as to when one thread will 'see' the changes made to it by the other. And typically, if you keep one thread occupied like you're doing here (this while loop is called a busy wait) it will never take the time to synchronize, and you'll never see the updates.

The println is an IO operation, meaning at some point your thread will be waiting for IO to complete. Most likely this causes the JVM to synchronize the variables, which is why you notice this difference.

In any case, relying on this without thinking about synchronization can be considered a bug.

Java threads and memory handling are a complex subject, and not something I would advise for beginners to jump in to; it could be overwhelming. Just try to avoid sharing memory between threads for now. For the moment, just run your logic in your swing application code (it's not ideal, but for some beginner code it's probably a good starting point).

When you feel ready for it, read up on the memory model and what it implies for multi-threading.

Upvotes: 1

Related Questions