2012-04-24 77 views
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();

回答

0

幫你自己一個忙,並重寫代碼,以使用CountDownLatch而不是低級的等待通知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(); 
    } 
} 
+0

我使用CoundDownLatch構造而不是wait/notify,但問題仍然存在。我想到它似乎取決於JVM。當我使用OpenJDK時,事件有時會丟失,當我使用Java Standard Edition時,問題不會發生。 – Thomas789 2012-04-24 09:50:17

+0

請發佈更改後的代碼。如果它依賴於jvm,那麼它就是99%,因爲你做錯了一些事情,只要它運行起來就很幸運。 – 2012-04-24 09:58:10

+0

我編輯了這個問題併發布了更改後的代碼,現在包含'CoundDownLatch'而不是'wait/notify' – Thomas789 2012-04-24 10:38:18