2011-12-27 2 views
2

다른 스레드에서 4 개의 MP3 트랙을 동시에 실행하려고합니다. MP3를 재생하려면 JLayer1.0 MP3 library을 사용하고 있습니다. 스레드가 시작될시기를 제어 할 수 없다는 것을 감안할 때 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이 이미 자바로 구현되었다는 것을 알고 있지만, 내가 원하는 것보다 더 복잡해 보인다.

+0

그냥 생각해보십시오. 어쩌면 다중 트랙 재생은 원하는만큼 복잡 할 수 있습니다. 스레드는 쉽게 제어되지 않고 쉽게 동기화되지 않습니다. 이 일이 자동으로 수행된다면, 고통을 잊어 버려라. 누군가 이미 알아 냈어. (그리고 다시,이 퍼즐들이 당신을 즐겁게한다면, 행운을 빈다) –

답변

1

CountdownLatch API를 읽으면 사용하려는 방식대로 사용할 수 있는지 궁금합니다.

"다른 스레드에서 수행되는 작업 집합이 완료 될 때까지 하나 이상의 스레드를 대기시킬 수있는 동기화 지원 도구입니다."

CountDownLatch를 예제의 실행 방법은 다음과 같습니다

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(). 수 밀리 초.

마지막 편집 : 더 많이 CountdownLatch를 볼수록 더 많은 스레드가 동기화를 시작할 수 있다고 생각합니다. 각 스레드의 카운트 다운을 원하지 않는다면, 단지 다음을 원할 것입니다 :

startSignal.await(); 
play();