Java – no code is executed without a print statement
See English answer > loop doesn't see changed value without a print statement1
package main; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; public class Gatoo extends JFrame implements ActionListener { private int sec,min,secTot,since = 999; private long lastTime; private JTextField mm = new JTextField(2),ss = new JTextField(2); private JLabel minLab = new JLabel("Minutes:"),secLab = new JLabel( "Seconds:"); private JButton start = new JButton("Start"); private Clip done; private boolean started = false; private static final long serialVersionUID = 4277921337939922028L; public static void main(String[] args) { Gatoo cake = new Gatoo("Title"); cake.pack(); cake.setSize(800,600); cake.setLocationRelativeTo(null); cake.setDefaultCloSEOperation(3); cake.setVisible(true); cake.run(); } public Gatoo(String s) { super(s); setLayout(new FlowLayout()); start.addActionListener(this); add(minLab); add(mm); add(secLab); add(ss); add(start); } @Override public void actionPerformed(ActionEvent e) { started = true; } public void play(File file) throws MalformedURLException,UnsupportedAudioFileException,IOException,LineUnavailableException { AudioInputStream ais = AudioSystem.getAudioInputStream(new File( "lib/done.wav")); DataLine.Info info = new DataLine.Info(Clip.class,ais.getFormat()); done = (Clip) AudioSystem.getLine(info); done.open(ais); done.start(); } public void run() { while (true) { System.out.print("");// needed? if (started) { try { min = Integer.parseInt(mm.getText()); sec = Integer.parseInt(ss.getText()); secTot = (min * 60) + sec; lastTime = System.currentTimeMillis(); while (secTot > 0) { since = (int) (System.currentTimeMillis() - lastTime); if (since > 998) { lastTime = System.currentTimeMillis(); secTot--; } } play(new File("done.wav")); } catch (NumberFormatException exception) { System.out.println("Minutes and seconds must be numbers."); return; } catch (Exception exception) { exception.printStackTrace(); } started = false; } } } }
In the last while loop, if there is no print / println statement, the countdown code will not execute How? Nevertheless, the program works perfectly with the print statement
Solution
First, your program is thread unsafe because Boolean started is a shared variable, but it is neither mutable nor accessed in the synchronized block
Now, unexpectedly, printstream #print is a synchronization method, and on any actual architecture, memory barrier CPU instructions are used to enter and exit synchronization blocks, which leads to complete synchronization between thread local state and main memory
Therefore, by pure accident, adding a print call allows the setting of the start flag of one thread (EDT) to be visible to another (main thread)