2011-12-27 8 views
2

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

は、ここに私のプログラムです:

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トラックがタイミングを維持するための簡単な方法はありますか?私はすでにmultiple track playerがjavaで実装されていることを知っていますが、それは私が望むより複雑なようです。

+0

ちょっと考えました。たぶん、複数のトラックの再生は、あなたが望むほど正確に複雑です。スレッドは容易に制御されず、容易には同期されません。このことが自動的に行われる場合は、痛みを忘れないでください。誰かがすでにこれを理解しました。 (そして再び、これらのパズルがあなたを楽しませるなら、幸運) –

答えて

1

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

"他のスレッドで実行されている一連の操作が完了するまで、1つまたは複数のスレッドを待機させる同期化補助機能。"

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

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

それは、スタート信号を待つが、それはだ後、作業方法が完了するまでのカウントダウンを行いません。 CountdowLatchを誤って使用しているようで、メインスレッドが完了する前にすべてのスレッドが終了していることを確認するのが本来の目的です。

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

スレッドのOSスケジューリングが原因である可能性があります。つまり、JPlayer 1.0の開発者が解決策を見つけ出したのですが、ハードウェアとOSが協力していれば、 play()は各スレッドに対して同時に発生します。プラスまたはマイナス2ミリ秒です。

最後の編集:CountdownLatchをもっと見るほど、スレッドを同期させるために使用できると思います。各スレッドでカウントダウンしたくない場合は、次のようにします。

関連する問題