Java 行侦听器事件丢失
我尝试使用Java clip对象播放信号。我开始剪辑,然后等待停止事件被触发,直到我继续线程。我观察到,如果退出调用线程(这可能发生在我的应用程序中),声音不会播放或只播放第一部分 这在大多数情况下都可以正常工作,但是,每隔大约50次,启动和停止事件都不会被触发,这会导致当前线程永远等待 现在的问题是,我是否在同步方面做了一些错误的事情,使我失去了活动Java 行侦听器事件丢失,java,audio,Java,Audio,我尝试使用Java clip对象播放信号。我开始剪辑,然后等待停止事件被触发,直到我继续线程。我观察到,如果退出调用线程(这可能发生在我的应用程序中),声音不会播放或只播放第一部分 这在大多数情况下都可以正常工作,但是,每隔大约50次,启动和停止事件都不会被触发,这会导致当前线程永远等待 现在的问题是,我是否在同步方面做了一些错误的事情,使我失去了活动 private static volatile boolean isPlaying = false; private static final
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();
}
}
这是使用
倒计时闩锁:
我没有包括调试语句,但它们表明线程挂起在playingFinished.await中;因为停止事件未触发,播放已完成。倒计时;从未调用。请帮自己一个忙,重新编写代码,以使用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();
}
}
我使用conciddownlatch构造而不是wait/notify,但是问题仍然存在。我突然想到,它似乎依赖于JVM。当我使用OpenJDK时,事件有时会丢失,当我使用Java标准版时,问题不会发生。请发布更改后的代码。如果它依赖于jvm,那么它是99%,因为你做了一些错误的事情,当它工作时只是运气好而已。我编辑了这个问题并发布了更改后的代码,现在它包含了ConditDownLatch而不是wait/Notify。我所能看到的是,这段代码在CountDownLatch上包含了一个竞争条件。它可能会也可能不会导致你的问题,但如果你做对了,情况会好得多。您可能确实遇到了1%的问题,而真正的问题在于OpenJDK。请参阅更新答案中的代码。它可能只具有教育价值,对你的问题没有帮助。
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();
}
}