1

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

4

1 に答える 1

0

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();
  }
}
于 2012-04-24T08:57:36.910 に答える