2

異なるスレッドで同時に 4 つの MP3 トラックを実行しようとしています。私はJLayer1.0 MP3 ライブラリを使用して MP3 を再生しています。スレッドがいつ開始されるかを制御できないため、CountDownLatch を使用して、少なくとも同時に実行できるようにしています。ただし、プログラムを実行するたびにトラックは再生されますが、一貫して異なる時間に開始され、タイミングがずれます。

これが私のプログラムです:

public class MP3 {
    private String filename;
    private Player player; 
    private final CountDownLatch runlatch;

    // constructor that takes the name of an MP3 file
    public MP3(String filename, CountDownLatch runlatch) {
        this.filename = filename;
        this.runlatch = runlatch;
    }

    // play the MP3 file to the sound card
    public void play() {
        try {
            FileInputStream fis     = new FileInputStream(filename);
            BufferedInputStream bis = new BufferedInputStream(fis);
            System.out.println(filename);
            player = new Player(bis);
        }
        catch (Exception e) {
            System.out.println("Problem playing file " + filename);
            System.out.println(e);
        }

        // run in new thread to play in background
        Thread track = new Thread() {
            public void run() {
                try { 
                    try {
                        runlatch.countDown();
                        runlatch.await();
                        player.play();
                    } catch (InterruptedException e) {
                        System.out.println(e);
                    } 
                }
                catch (Exception e) { System.out.println(e); }
            }
        };
        track.start();
    }

    // test client
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch runlatch = new CountDownLatch(4);

        String filename1 = args[0];
        String filename2 = args[1];
        String filename3 = args[2];
        String filename4 = args[3];
        MP3 track1 = new MP3(filename1, runlatch);
        MP3 track2 = new MP3(filename2, runlatch);
        MP3 track3 = new MP3(filename3, runlatch);
        MP3 track4 = new MP3(filename4, runlatch);

        track1.play();
        track2.play();
        track3.play();
        track4.play();
    }
}

最終スレッドによってラッチが開かれた後、各スレッドがコードを実行する方法を制御できないことはわかっています。MP3 の再生開始時期をより詳細に制御するには、JLayer1.0 の実装に取り​​掛かる必要があるようです。

MP3 トラックのタイミングを維持する簡単な方法はありますか? 複数のトラック プレーヤーが Java で既に実装されていることは知っていますが、私が望むよりも複雑なようです。

4

1 に答える 1

1

CountdownLatch の API を読むと、使用しようとしている方法で使用できるかどうか疑問に思います。

「他のスレッドで実行されている一連の操作が完了するまで、1 つまたは複数のスレッドを待機できるようにする同期支援。」

CountdownLatch の例の run メソッドは次のようになります。

public void run() {
      try {
        startSignal.await();
        doWork();
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
  }

開始信号を待ちますが、作業メソッドが完了するまで countDown を実行しません。CountdowLatch を誤用しているようで、メインスレッドが完了する前にすべてのスレッドが終了することを確認することが本当の目的です。

だからここに私の提案があります:あなたがやっているように各スレッドを起動しますが、CountdownLatchを使用する代わりに、値がfalseに変わるまで静的ブール値で各スレッドをループさせます。そうすれば、すべてのスレッドを起動してから、ThreadLocal を false に設定でき、それらはすべて play() を呼び出す必要があります。これはおそらく製品品質のコードではなく、実際には各スレッドでイベントをリッスンする必要があることに注意してください。ただし、試してみてください。

全体的な問題は、スレッドの OS スケジューリングが原因であり、それが JPlayer 1.0 開発者が解決策を見つけたものである可能性がありますが、ハードウェアと OS が連携している場合は、play() を取得して実行できるはずです。スレッドごとにプラスまたはマイナス数ミリ秒同時に発生します。

最終編集: CountdownLatch を見れば見るほど、それを使用してスレッドの開始を同期できると思います。各スレッドでカウントダウンは必要ありません。必要なのは次のとおりです。

startSignal.await();
play();
于 2012-06-17T14:53:18.637 に答える