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();
呼び出されないため、スレッドがハングインしていることを示しています。