我尝试使用 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();
从未调用过。