我尝试使用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();
。
答案 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();
}
}