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)

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>