2012-04-24 11 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); 


は、私はデバッグ文が含まれていませんでしたが、彼らはSTOPイベントが発生していなかったため、スレッドがplayingFinished.await();でハングことを示していますplayingFinished.countDown();は呼び出されません。

答えて

0

低レベルの待機通知APIの代わりにCountDownLatchを使用するように自分でコードを書き直してください。あなたの問題は、それだけで蒸発するかもしれません。

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構成を使用しましたが、問題は依然として残ります。それはJVMに依存しているように思えます。 OpenJDKを使用するとイベントが失われることがありますが、Java Standard Editionを使用すると問題は発生しません。 – Thomas789

+0

変更されたコードを投稿してください。それがjvmに依存している場合は、何か間違っていて動作しているだけで運が良ければ99%です。 –

+0

私は質問を編集し、変更されたコードを掲示しました。これには 'wait/notify'の代わりに' CoundDownLatch'が含まれています。 – Thomas789