Воспроизведение нескольких дорожек MP3 в разных потоках - PullRequest
2 голосов
/ 28 декабря 2011

Я пытаюсь запустить 4 трека MP3 одновременно в разных потоках.Я использую MP3-библиотеку JLayer1.0 для воспроизведения 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();
    }
}

Я знаю, чтоЯ не могу контролировать, как каждый поток выполняет код после открытия защелки последним потоком.Похоже, что мне нужно было бы войти в реализацию JLayer1.0, чтобы иметь больше контроля над тем, когда MP3 начнут воспроизводиться.

Есть ли какой-нибудь простой способ заставить треки MP3 оставаться синхронизированными на протяжении всей их продолжительности?Я знаю, что многодорожечный проигрыватель уже реализован в Java, но он кажется более сложным, чем я хочу.

1 Ответ

1 голос
/ 17 июня 2012

Чтение API для CountdownLatch заставляет меня задуматься, можете ли вы использовать его так, как вы пытаетесь его использовать.

"Средство синхронизации, позволяющее одному или нескольким потокам дождаться завершения набора операций, выполняемых в других потоках."

Метод run в примере CountdownLatch выглядит следующим образом:

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

Он ожидает сигнала запуска, но не выполняет countDown, пока не завершится его метод работы. Похоже, вы неправильно используете CountdowLatch, и его реальная цель - убедиться, что все потоки завершены до того, как основной поток может завершиться.

Итак, вот мое предложение: запускать каждый поток, как вы, но вместо использования CountdownLatch, каждый цикл цикла должен быть статическим логическим значением, пока значение не изменится на false. Таким образом, вы запускаете все потоки, затем вы можете установить для ThreadLocal значение false, и все они должны вызывать play (). Обратите внимание, что это, вероятно, не код производственного качества, и вам действительно нужно, чтобы каждый поток прослушивал событие, но попытайтесь.

Общая проблема может заключаться в том, что виноваты в планировании потоков ОС, и именно в этом разработчики JPlayer 1.0 придумали решение, но если аппаратное и операционное взаимодействие взаимодействуют, оно должно быть в состоянии добиться успеха. () происходит одновременно для каждого потока плюс или минус пара миллисекунд.

Последнее редактирование: чем больше я смотрю на CountdownLatch, тем больше я думаю, что вы можете использовать его для синхронизации запуска потоков. Вы не хотите обратного отсчета в каждой теме, вы просто хотите:

startSignal.await();
play();
...