当前位置: 首页 > 知识库问答 >
问题:

在没有打印语句的情况下未执行代码[重复]

居飞扬
2023-03-14

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

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语句配合得非常好。

共有3个答案

薛枫
2023-03-14

听着,我复制了这个行为。这是一个非常好的问题。

public class ThreadRacing implements Runnable
{
    public boolean started = false;

    public static void main(String[] args)
    {
        new ThreadRacing().test();
    }

    public void test()
    {
        new Thread(this).start();
        try
        {
            Thread.sleep(1000);
        } catch (Exception e)
        {

        }
        started = true;
        System.out.println("I did my job");
    }

    @Override
    public void run()
    {
        while (true)
        {
            //System.out.print("");
            if (started)
            {
                System.out.println("I started!!");
            }
        }
    }

}

这幅画是:“我做了我的工作”。而已。添加易失性关键字实际上可以解决问题。

在我看来,第二个线程似乎没有收到关于已启动的更新的通知,因为他太忙了。

卫博雅
2023-03-14

您的Swing应用程序设计很差。

    < li >不要在< code>run()方法中使用< code>while(true)循环。阅读更多关于Swing中并发性的内容。 < li >借助< code>Listeners(例如< code>ActionListener)而不是标志(此处为< code>started)调用事件。 < li >使用Swing Timer代替计时。

更改您的< code>run()方法,如下所示:

public void run() {
      min = Integer.parseInt(mm.getText());
      sec = Integer.parseInt(ss.getText());
      secTot = (min * 60) + sec;
      Timer timer = new Timer(1000*secTot, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
              try {
                play(new File("done.wav"));
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    });
      timer.start();
}

< code>actionPerformed()方法:

@Override
public void actionPerformed(ActionEvent e) {
    run();
}

并删除cake。main方法中的run()

史钊
2023-03-14

首先,您的程序是线程不安全的,因为< code>boolean started是一个共享变量,但它既不是< code>volatile也不能在同步块中访问。

现在,意外地,PrintStream#print是一种同步方法,在任何实际的体系结构上,进入和退出同步块都是使用内存屏障CPU指令实现的,这会导致线程本地状态和主内存之间的完全同步。

因此,添加print调用纯粹是偶然的,它允许一个线程(EDT)设置的startedflag被另一线程(主线程)看到。

 类似资料:
  • 问题内容: 我一直在做倒计时计划,我想到了这个。 在while循环的最后,没有内部的print / println语句,倒计时代码将不会执行。怎么会?该程序可以很好地与print语句一起工作。 问题答案: 首先,您的程序是 线程不安全的, 因为它是一个 共享变量 ,但是在同步块中既不访问也不访问。 现在,偶然地是一种同步方法,并且在任何实际架构上,使用 内存屏障 CPU指令来实现进入和退出同步块,

  • 问题内容: 我想知道是否有一种方法可以打印没有换行符的元素,例如 并且将打印而不是通常打印的内容 谢谢! 问题答案: 这可以用轻松完成打印() 函数 与 Python 3中 。 会给你 在 Python v2中, 您可以通过以下方式使用该函数: 作为源文件中的 第一条 语句。 如print()文档所述: 请注意,这类似于我最近回答的问题(https://stackoverflow.com/a/12

  • 问题内容: 我想知道在不提示输入密码的情况下执行数据库mysqldump的命令。 原因:我想运行一个cron作业,该作业每天执行一次mysqldump数据库的转储。因此,出现提示时,我将无法插入密码。 我该如何解决? 问题答案: 由于您正在使用Ubuntu,因此您所要做的只是在主目录中添加一个文件,这将禁用mysqldump密码提示。这是通过创建文件来完成的(权限需要为600)。 将此添加到.my

  • 我有一个我不知道如何解决的问题。 我想用

  • 问题内容: 我正在寻找没有浏览器的Javascript编程。我想从Linux或MacOSX命令行运行脚本,就像我们运行任何其他脚本语言(ruby,PHP,Perl,Python …)一样 我研究了spider monkey(Mozilla)和v8(Google),但它们似乎都是嵌入式的。 是否有人将Javascript作为脚本语言从命令行执行? 如果有人好奇,为什么我期待到这一点,我一直在关注着N

  • 问题内容: 我正在尝试修复这段代码,该代码是从具有车牌号和车主列表(该格式)的哈希图进行打印的。我试图通过printOwners()仅打印出所有者;但是我不能不打印重复的东西。 我已经玩了一段时间,但似乎无法跳过重复项。 这是我的代码: 问题答案: 要删除重复项,请使用: 或者使用Java 8 和方法: