Java程序在停止音频时挂起

时间:2014-07-09 12:37:30

标签: java

我为一个简单的音乐播放器编写了这段代码,问题是当我点击openLabel并打开一首歌然后当我通过点击playLabel暂停它时程序停止执行(程序挂起)。

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.Random;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;  

public class A extends MouseAdapter implements ChangeListener, Runnable {
    private ImageIcon playImage = new ImageIcon(getClass().getResource("Images/play.png"));
    private ImageIcon pauseImage = new ImageIcon(getClass().getResource("Images/pause.png"));
    private ImageIcon openImage = new ImageIcon(getClass().getResource("Images/open.png"));
    private JLabel playLabel = new JLabel(playImage);
    private JLabel openLabel = new JLabel(openImage);
    public JFrame frame = new JFrame();
    public JPanel colorPanel = new JPanel();
    private enum Status {ON,OFF,PAUSE,END};
    private Status playStatus=Status.OFF;
    private JSlider slider = new JSlider();
    public Clip songClip;   
    Thread screenThread = new Thread(this);

    public static void main(String arg[]) throws Exception {
        new A();
    }

    public A() throws Exception {
        setFrame();
        setComponents();
    }

    public void setFrame() {
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setUndecorated(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setCursor(new Cursor(Cursor.HAND_CURSOR));
        frame.getContentPane().setBackground(Color.BLACK);
        frame.setVisible(true);
    }

    public void setComponents() {
        slider.setBounds(0,640,1000,15);
        slider.setBackground(Color.BLACK);
        slider.addChangeListener(this);
        slider.setValue(0);
        playLabel.setBounds(450,665,100,100);
        playLabel.addMouseListener(this);
        openLabel.setBounds(540,690,60,60);
        openLabel.addMouseListener(this);
        colorPanel.setBackground(Color.BLACK);
        colorPanel.setBounds(0,100,1500,500);
        frame.add(openLabel);
        frame.add(playLabel);
        frame.add(colorPanel);
        frame.add(slider);
    }

    public void mouseClicked(MouseEvent clicked) {
        if (clicked.getSource() == openLabel) {
            openLabel.setIcon(openImage);
            open();
        }
        else if (clicked.getSource()==playLabel && playStatus != Status.OFF) {
            if (playStatus == Status.PAUSE) {
                songClip.start();
                screenThread.resume();
                playStatus=Status.ON;
                playLabel.setIcon(pauseImage);
            }
            else if (playStatus == Status.ON) {
                songClip.stop();
                screenThread.suspend();
                playStatus=Status.PAUSE;
                playLabel.setIcon(playImage);
            }
            else if (playStatus==Status.END) {
                songClip.setMicrosecondPosition(0);
                slider.setValue(0);
                songClip.start();
                screenThread.resume();
                playStatus = Status.ON;
                playLabel.setIcon(pauseImage);
            }
        }
    }

    public void stateChanged(ChangeEvent e) {
        if (playStatus != Status.OFF) {
            JSlider jslider = (JSlider)e.getSource();
            int position = jslider.getValue();
            songClip.setMicrosecondPosition(position * 1000000);
        }
    }

    public void open() {
        JFileChooser chooseSong = new JFileChooser();
        chooseSong.setFileSelectionMode(JFileChooser.FILES_ONLY);
        chooseSong.setFileFilter(new FileNameExtensionFilter(null, "wav"));
        int chooseButton = chooseSong.showOpenDialog(null);
        File songPath = chooseSong.getSelectedFile();

        if ( (chooseButton!=JFileChooser.CANCEL_OPTION) && (songPath!=null) && (songPath.getName() != null) ) {
            try {
                playLabel.setIcon(pauseImage);
                if (playStatus != Status.OFF)
                    songClip.close();

                AudioInputStream songFile = AudioSystem.getAudioInputStream(songPath);
                songClip = AudioSystem.getClip();
                songClip.open(songFile);

                int clipLength = (int)(songClip.getMicrosecondLength() / 1000000);
                slider.setMinimum(0);
                slider.setMaximum(clipLength);
                songClip.start();

                if (playStatus == Status.OFF)
                    screenThread.start();
                else if (playStatus != Status.OFF)
                    screenThread.resume();

                playStatus=Status.ON;
            }
            catch(Exception exp) {
                Toolkit.getDefaultToolkit().beep();
                JOptionPane.showMessageDialog(null, String.format("ERROR = %s",exp.getClass()));
                System.exit(0);
            }
        }
    }

    public void run() {
        while (true) {
            colorPanel.setBackground(new Color(new Random().nextInt(256), new Random().nextInt(256), new Random().nextInt(256)));           
            if (songClip.getMicrosecondPosition() == songClip.getMicrosecondLength()) {
                screenThread.suspend();
                playStatus=Status.END;
                playLabel.setIcon(playImage);
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您正在响应单击播放/暂停按钮的块中调用screenThread.suspend();。线程方法suspend()resume()容易出现死锁 - 也就是说,使用它们通常会导致难以诊断的问题,例如您所拥有的问题。

您需要通过轮询变量来删除这些方法的使用,如this page所述。

答案 1 :(得分:0)

  

此方法已被弃用,因为它本身就容易出现死锁。

这是Thread.stop().suspend().resume()弃用的原因。正如您在代码中使用它们一样,这可能是问题所在。