Как подружить Swing и синхронизированные потоки

Рейтинг: 1Ответов: 1Опубликовано: 05.05.2015

Пишу плеер, и возникла заминка в следующем: есть главный поток из Swing, и есть параллельные ему потоки, которые должны запускаться последовательно друг за другом. Как подружить эти потоки, но так, чтобы и параллельные потоки запускались друг за другом и графический интерфейс не "замерзал" при работе этих потоков?

tagTopTracks хранит коллекцию треков для воспроизведения, требуется проиграть весь этот плейлист последовательно.

AppGUI (сокращенно) - Swing-интерфейс

public class AppGUI extends javax.swing.JFrame {

private TopTracks tagTopTracks;
private int trackNumber;
private Track track;

PlayerClass player = new PlayerClass();
private void playButtonMouseReleased(java.awt.event.MouseEvent evt) {
    while (trackNumber < tagTopTracks.getTopTracks().size()) {
        getTrackFromTopTracks(trackNumber);
        player.stop();
        player.play(track.getTrackURL());
        trackNumber++;
    }
    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new AppGUI().setVisible(true);
        }
    });

}

Класс, который заведует плеером:

public class PlayerClass {

private static URL url;
private static InputStream is;
private static BufferedInputStream bis;

public Player player;

public void stop() {
    if (player != null) {
        player.close();
    }
}

public void play(String fileURL) {
    try {

        url = new URL(fileURL);
        URLConnection connection = url.openConnection();
        is = connection.getInputStream();
        bis = new BufferedInputStream(is);
        player = new Player(bis);

    } catch (MalformedURLException ex) {

    } catch (IOException ex) {

    } catch (JavaLayerException ex) {

    }

    new Thread() {
        @Override
        public void run() {
            try {
                player.play();
            } catch (JavaLayerException ex) {

            }
        }
    }.start();
}

}

И здесь возникают проблемы с последовательным воспроизведением треков из плейлиста: новый трек начинает играть, не дожидаясь окончания предыдущего, накладываясь на него, потом третий, четвертый и так далее. Если же сделать метод run() синхронизированным, то треки, как и требуется, играют один за одним, но тогда "замерзает" GUI.

Ответы

▲ 1Принят

Вам нужно пересмотреть архитектуру вашего плеера. Вместо того, чтобы в цикле запускать потоки с воспроизведением, попробуйте заставлять поток воспроизведения песни автоматически запускать следующую по окончанию воспроизведения. Для того, чтобы поток знал, какую песню запускать следующей, нужно либо при создании потока-песни передавать ссылку на следующую (негибко, не позволяет динамически менять плейлист), либо хранить плейлист в каком-нибудь месте, где к нему будут иметь доступ потоки, воспроизводящие песни (читайте про паттерн "Синглтон"). Более гибкий вариант - по окончанию воспроизведения трек генерирует событие, которое ожидает какой-нибудь менеджер воспроизведения (читайте про паттерн "Наблюдатель"), который, в свою очередь, по этому событию запускает воспроизведение следующего трека.