java - 没有 print 语句的代码不执行

标签 java swing java-7

<分区>

我一直在制作一个倒计时程序,我想到了这个。

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

在最后的 while 循环中,如果内部没有 print/println 语句,倒计时代码不会执行。怎么会?不过,该程序与 print 语句配合得很好。

最佳答案

首先,您的程序是线程不安全的,因为boolean started 是一个共享变量,但它既不是易变的 也不在同步块(synchronized block)内访问。

现在,意外地,PrintStream#print 是一个同步方法,在任何实际架构上,进入和退出同步块(synchronized block)是使用 内存屏障 CPU 指令实现的,它导致线程本地状态和主内存之间的完全同步。

因此,纯属意外,添加 print 调用允许一个线程(EDT)设置 started 标志可见由另一个(主线程)。

关于java - 没有 print 语句的代码不执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20786483/

相关文章:

java - 在 Swing 中构建一个类似于 SO 标记的搜索模块 UI

android - 错误 : Default interface methods are only supported starting with Nougat (--min-api 24) when NOT using them

ssl - 启用 TLSv1.2 和 TLS_RSA_WITH_AES_256_CBC_SHA256 密码套件

java - gwt 接口(interface) HostedModeOptions 扩展了超过 1 个类

java - Struts2 - 我如何使用 <s :a> without previously knowing the action that I'll use?

java - 如何迭代字符串多次提取并存储特定内容

java - Guava SetMultimap 不可序列化(由于不可序列化 WrappedSet)

java - WireMockRule 在集成测试中不适用于非本地主机

java - 动态编辑 JCombobox 中的项目

java - 我不希望 JTable 用省略号截断文本