javax.sound.sampled它是如何工作的?

javax.sound.sampled它是如何工作的?,java,audio,javasound,Java,Audio,Javasound,我正在尝试用Java播放声音。 到目前为止进展顺利,谢谢,但我在理解这是如何工作的时候遇到了一个问题 我编写了一个函数来进行播放: private static void PlaySound(String path) { try { final File SoundFile = new File(path); AudioInputStream Sound = AudioSystem.getAudioInputStream(S

我正在尝试用Java播放声音。 到目前为止进展顺利,谢谢,但我在理解这是如何工作的时候遇到了一个问题

我编写了一个函数来进行播放:

    private static void PlaySound(String path) {
        try {
            final File SoundFile = new File(path);
            AudioInputStream Sound = AudioSystem.getAudioInputStream(SoundFile);

            DataLine.Info info = new DataLine.Info(Clip.class, Sound.getFormat());
            Clip clip = (Clip) AudioSystem.getLine(info);
            clip.open(Sound);

            clip.addLineListener(new LineListener() {
                public void update (LineEvent event) {
                    if (event.getType() == LineEvent.Type.STOP) {
                        event.getLine().close();
                        System.out.printf("Playback ended!");
                        System.exit(0);
                    }
                }
            });
            System.out.printf("This sound is %f seconds long.", (clip.getMicrosecondLength() / 1000.0d));
            clip.start();
        } catch (Exception e) {
            ErrorHandler(e);
        }
    }
现在这个函数几乎可以正常工作了:当声音结束时,它调用event.getLine().close();函数,但它被卡在一个“无限循环”(不确定是否是)中,并且在执行该语句后什么都没有,程序运行直到我手动终止它

如果我换线

if (event.getType() == LineEvent.Type.STOP) {

然后声音播放,程序正确退出,但事件后仍然没有任何语句。getLine().close();他们被处决了

问题是:这是event.getLine().close()的预期行为,还是我做错了什么


解决方案:


LineListener实际上基于一个过时的事实,即Java声音中有一个bug,我们需要显式地从vm中退出。没有侦听器,代码就可以正常工作。

查看是否引发异常:

public void update (LineEvent event) {
  if (event.getType().equals(LineEvent.Type.STOP)) {
    try { 
      event.getLine().close();
    } catch (Throwable t) {
      t.printStackTrace();
    }
    System.out.printf("Playback ended!");
  }
}

没有从事件.getLine().close()引发异常。顺便说一句,如果存在未处理的异常,代码将实际退出并出现错误(-:@estol如果在主线程中,未处理的异常只会导致程序终止并出现错误。我想看看是否由于
close()而引发了
ThreadDeath
正在终止一个事件传递线程。此时程序由一个线程组成:上面的函数和调用PlaySound()的主函数传递了/home/estol/sounds/testfiles/2sec.wav参数的函数。这只是一个实验,看看它是如何工作的。@estol使用声音包将创建额外的后台线程。这就是为什么程序有时不会在主线程终止时终止。调用
close()的原因之一
的作用是停止这些线程。当然它会创建一些线程,但我不能完全确定这个对象的工作机制,但是如果我调用close,为什么它会挂起而不是终止?
public void update (LineEvent event) {
  if (event.getType().equals(LineEvent.Type.STOP)) {
    try { 
      event.getLine().close();
    } catch (Throwable t) {
      t.printStackTrace();
    }
    System.out.printf("Playback ended!");
  }
}