Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 行侦听器事件丢失_Java_Audio - Fatal编程技术网

Java 行侦听器事件丢失

Java 行侦听器事件丢失,java,audio,Java,Audio,我尝试使用Java clip对象播放信号。我开始剪辑,然后等待停止事件被触发,直到我继续线程。我观察到,如果退出调用线程(这可能发生在我的应用程序中),声音不会播放或只播放第一部分 这在大多数情况下都可以正常工作,但是,每隔大约50次,启动和停止事件都不会被触发,这会导致当前线程永远等待 现在的问题是,我是否在同步方面做了一些错误的事情,使我失去了活动 private static volatile boolean isPlaying = false; private static final

我尝试使用Java clip对象播放信号。我开始剪辑,然后等待停止事件被触发,直到我继续线程。我观察到,如果退出调用线程(这可能发生在我的应用程序中),声音不会播放或只播放第一部分

这在大多数情况下都可以正常工作,但是,每隔大约50次,启动和停止事件都不会被触发,这会导致当前线程永远等待

现在的问题是,我是否在同步方面做了一些错误的事情,使我失去了活动

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();
  }
}