线路侦听器事件丢失

时间:2012-04-24 08:10:13

标签: java audio

我尝试使用Java剪辑对象播放信号。我启动剪辑,然后等待STOP事件被触发,直到我继续该线程。我观察到如果我退出调用线程,这可能发生在我的应用程序中,声音不播放或只播放第一部分。

这大部分时间都可以正常工作,但是,每隔大约50次,START和STOP事件都不会被触发,这会导致当前线程永远等待。

现在的问题是,我是否对同步做错了什么让我放松了事件?

private static volatile boolean isPlaying = false;
private static final Object waitObject = new Object();

public static void playClip(...)

...

    Clip clip = (Clip) AudioSystem.getLine(...);

    clip.addLineListener(new LineListener() {
        public void update(LineEvent event) {
            if (event.getType() == LineEvent.Type.STOP) {
                event.getLine().close();
                synchronized (waitObject) {
                    isPlaying = false;                        
                    waitObject.notifyAll();
                }
            }
        }
    });


    // start playing clip
    synchronized (waitObject) { 
        isPlaying = true;
    }
    clip.start();

    // keep Thread running otherwise the audio output is stopped when caller thread exits
    try {
        while (isPlaying) {
            synchronized (waitObject) {
                waitObject.wait();                    
            }
        }
    } catch (InterruptedException e) {           
        e.printStackTrace();
    }
}

以下是使用 CountDownLatch的新版本:

private static volatile CountDownLatch playingFinished = new CountDownLatch(1);

public static void playClip(...)

...
    Clip clip = (Clip) AudioSystem.getLine(...);
    clip.open(audioInputStream);

    // use line listener to take care of synchronous call
    clip.addLineListener(new LineListener() {
        public void update(LineEvent event) {
            if (event.getType() == LineEvent.Type.STOP) {
                event.getLine().close();
                playingFinished.countDown();
            }
        }
    });

    clip.start();

    try {
        playingFinished.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    playingFinished = new CountDownLatch(1);


我没有包含调试语句,但是它们表明线程在playingFinished.await();中挂起,因为没有触发STOP事件而且从不调用playingFinished.countDown();

1 个答案:

答案 0 :(得分:0)

帮自己一个忙,然后重新编写代码,使用CountDownLatch代替低级wait-notify API。您的问题可能会自行消失。

public void playClip() throws Exception {
  final CountDownLatch playingFinished = new CountDownLatch(1);
  final Clip clip = (Clip) AudioSystem.getLine(...);
  clip.open(...);
  clip.addLineListener(new LineListener() {
    public void update(LineEvent event) {
      if (event.getType() == LineEvent.Type.STOP) {
        event.getLine().close();
        playingFinished.countDown();
      }
    }
  });
  clip.start();
  try {
    playingFinished.await();
  } catch (InterruptedException e) {
    Thread.currentThread().interrupt();
  }
}