0
我嘗試使用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();
掛起,因爲停止事件沒有被解僱,並永遠不會調用playingFinished.countDown();
。
我使用CoundDownLatch構造而不是wait/notify,但問題仍然存在。我想到它似乎取決於JVM。當我使用OpenJDK時,事件有時會丟失,當我使用Java Standard Edition時,問題不會發生。 – Thomas789 2012-04-24 09:50:17
請發佈更改後的代碼。如果它依賴於jvm,那麼它就是99%,因爲你做錯了一些事情,只要它運行起來就很幸運。 – 2012-04-24 09:58:10
我編輯了這個問題併發布了更改後的代碼,現在包含'CoundDownLatch'而不是'wait/notify' – Thomas789 2012-04-24 10:38:18