2012-03-11 9 views
3

私は、動作するJavaプログラム、単純なmp3プレーヤーを持っています。IllegalThreadStateException?スレッドに慣れていない

すべてが動作し、トラックをスキップすることができます...しかし、いくつかのスキップ(特に前のトラック)の後、私はいつもIllegalThreadStateExceptionを取得します。 (。

この学校の割り当てのためである、とMP3のクラスは、私たちに与えられている。(変更することはできません)

任意のヒントをいただければ幸いです!ありがとう!

MP3のクラスを行うにはできません変更される):

import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import javazoom.jl.player.Player; 


public class MP3 extends Thread { 
    private final File mp3_file; 
    private Player player; 

    public MP3(String mp3_path) { 
    mp3_file = new File(mp3_path); 
} 

    public MP3(File mp3) { 
    mp3_file = mp3; 
} 

    public void play() { 
    try { 
     FileInputStream fis  = new FileInputStream(mp3_file); 
     BufferedInputStream bis = new BufferedInputStream(fis); 
     player = new Player(bis); 
    } 
    catch (Exception e) { 
     System.out.println("Problem playing file " + mp3_file); 
     System.out.println(e); 
    } 

    // run in new thread to play in background 
    start(); // Instructs JVM to call run() in separate thread 

    } 

    public boolean isPlaying() { 
    if (player == null) 
     return false; 
    else { 
     return !player.isComplete(); 
    } 

    } 

    public void run() { 
    try { player.play(); } 
    catch (Exception e) { System.out.println(e); } 
    } 


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

    public String toString() { 
    return mp3_file.toString(); 
    } 
} 

マイコード:

import javax.swing.*; 

public class MP3Random extends JFrame { 

private JPanel backgroundPanel; 
private PlaylistPanel playlistPanel; 
private MainPanel mainPanel; 

int trackTime; 
private MP3 current; 

private ButtonListener buttonListener; 
private TimerListener timerListener; 

private Timer timer; 
private boolean playButtonStatus; 

public MP3Random() { 

    buttonListener = new ButtonListener(); 
    timerListener = new TimerListener(); 

    backgroundPanel = new JPanel(); 
    mainPanel = new MainPanel(); 
    playlistPanel = new PlaylistPanel(); 

    timer = new Timer(1000, timerListener); 
    timer.setInitialDelay(0); 
    playButtonStatus = false; 

    setMinimumSize(new Dimension(650, 400)); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    getContentPane().setLayout(new BorderLayout(0, 0)); 

    backgroundPanel.setLayout(new BorderLayout(0, 0)); 
    backgroundPanel.setBorder(null); 
    backgroundPanel.add(playlistPanel, BorderLayout.CENTER); 
    backgroundPanel.add(mainPanel, BorderLayout.NORTH); 

    getContentPane().add(backgroundPanel); 
    setVisible(true); 
} 

private void playSong(MP3 current) { 
    ImageIcon stopIcon = new ImageIcon(MP3Random.class.getResource("/pa2/icons/stop.png")); 

     playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current)); 
    mainPanel.playButton.setIcon(stopIcon); 
    trackTime = 0; 
    current.play(); 
    timer.restart(); 
    mainPanel.trackTitleLabel.setText(getTrackTitle(current.toString())); 
} 

private void stopPlayback() { 
    try { 
     current.quit(); 
     timer.stop(); 
     playButtonStatus = false; 
     mainPanel.trackTitleLabel.setText(""); 
     mainPanel.trackTimeLabel.setText(""); 
     mainPanel.playButton.setIcon(mainPanel.playIcon); 
    } 
    catch (Exception e) {}; 
} 

private String getTrackTitle (String filename) { 
    return filename.substring(filename.lastIndexOf('/')+1, filename.lastIndexOf(".mp3")); 
} 

private String formatTime(int durationInSeconds) { 

    int minutes = durationInSeconds/60; 
    int seconds = durationInSeconds % 60; 

    return ((minutes < 10 ? "0" : "") + minutes 
      + ":" + (seconds< 10 ? "0" : "") + seconds); 
} 

//Panel containing track display/time, media control buttons 
private class MainPanel extends JPanel {...} 

//Panel containing JList and add/remove from playlist buttons 
private class PlaylistPanel extends JPanel {...} 

private class ButtonListener implements ActionListener { 

    File[] filesSelected; 
    MP3[] mp3List; 
    Random generator = new Random(); 

    public void actionPerformed (ActionEvent event) { 

     if (event.getSource() == playlistPanel.addButton) { 
      playlistPanel.fileChooser = new JFileChooser(); 
      playlistPanel.fileChooser.setMultiSelectionEnabled(true); 

      //FileFilter only allows *.mp3 
      playlistPanel.fileChooser.setAcceptAllFileFilterUsed(false); 
      playlistPanel.fileChooser.setFileFilter(new FileFilter() { 

       public boolean accept(File f) { 
        if (f.isDirectory()) 
         return true; 

        String extension = f.toString().substring(f.toString().lastIndexOf('.')+1); 
        if (extension != null) { 
         if (extension.equals("mp3")) 
          return true; 
         else 
          return false; 
        } 
        return false; 
       } 

       public String getDescription() { 
        return "*.mp3"; 
       } 
      }); 

      if (playlistPanel.fileChooser.showOpenDialog(MP3Random.this) == JFileChooser.APPROVE_OPTION) { 

       filesSelected = playlistPanel.fileChooser.getSelectedFiles(); 
       mp3List = new MP3[filesSelected.length]; 

       mainPanel.playButton.setEnabled(true); 
       playlistPanel.removeButton.setEnabled(true); 

       //more than 1 file selected 
       if (mp3List.length > 1) { 
        mainPanel.shuffleButton.setEnabled(true); 
        mainPanel.nextButton.setEnabled(true); 
       } 
       for (int i = 0; i < mp3List.length; i++) 
        playlistPanel.listModel.addElement(mp3List[i] = new MP3(filesSelected[i])); 
       current = (MP3) playlistPanel.listModel.get(0); 
       playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current)); 
      } 
     } 

     //remove button 
     if (event.getSource() == playlistPanel.removeButton) { 
      Object[] temp = playlistPanel.playList.getSelectedValues(); 
      for (Object f : temp) { 
       playlistPanel.listModel.removeElement(f); 
      } 

      //1 song in list 
      if (playlistPanel.listModel.getSize() == 1) { 
       mainPanel.backButton.setEnabled(false); 
       mainPanel.nextButton.setEnabled(false); 
       mainPanel. shuffleButton.setEnabled(false); 
      } 

      //no songs in list 
      if (playlistPanel.listModel.getSize() == 0) { 
       playlistPanel.removeButton.setEnabled(false); 
       mainPanel.playButton.setEnabled(false);    
       mainPanel.backButton.setEnabled(false); 
       mainPanel.nextButton.setEnabled(false); 
       mainPanel.shuffleButton.setEnabled(false); 
       current = null; 
      } 
     } 

     //play button 
     if (event.getSource() == mainPanel.playButton) { 

      //if song not playing 
      if (!playButtonStatus) { 
       if (!playlistPanel.playList.isSelectedIndex(playlistPanel.listModel.indexOf(current))) 
        current = (MP3) playlistPanel.playList.getSelectedValue(); 
       playSong(current);     
       playButtonStatus = true; 
      } 

      //if song is playing 
      else 
       stopPlayback(); 
     } 

     //next button 
     if (event.getSource() == mainPanel.nextButton) { 
      if (!mainPanel.backButton.isEnabled()) 
       mainPanel.backButton.setEnabled(true); 

      if (current.isPlaying()) { 
       current.quit(); 
       current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)+1); 
       playSong(current); 
      } 
      else { 
       current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)+1); 
       playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current)); 
      } 

      if (playlistPanel.listModel.indexOf(current) == playlistPanel.listModel.size() - 1) 
       mainPanel.nextButton.setEnabled(false); 
     } 

     //back button 
     if (event.getSource() == mainPanel.backButton) { 

      if (!mainPanel.nextButton.isEnabled()) 
       mainPanel.nextButton.setEnabled(true); 

      if (current.isPlaying()) { 
       current.quit(); 
       current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)-1); 
       playSong(current); 
      } 
      else { 
       current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)-1); 
       playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current)); 
      } 

      if (playlistPanel.listModel.indexOf(current) == 0) 
       mainPanel.backButton.setEnabled(false); 
     } 

     //shuffle jlist 
     if (event.getSource() == mainPanel.shuffleButton) { 
      if (playlistPanel.listModel.size() > 1) { 
       int n = playlistPanel.listModel.getSize(); 
       while (n > 1) { 
        int k = generator.nextInt(n); 
        n--;     
        MP3 tempMP3 = (MP3) playlistPanel.listModel.elementAt(n); 
        playlistPanel.listModel.set(n,playlistPanel.listModel.elementAt(k)); 
        playlistPanel.listModel.set(k, tempMP3); 
        current = (MP3) playlistPanel.listModel.get(0); 
        playlistPanel.playList.setSelectedIndex(playlistPanel.listModel.indexOf(current)); 
       } 
      } 
     } 
    } 
} 

private class TimerListener implements ActionListener { 

    public void actionPerformed(ActionEvent event) { 

     if (playlistPanel.listModel.indexOf(current) > 0) 
      mainPanel.backButton.setEnabled(true); 
     if (playlistPanel.listModel.indexOf(current) == playlistPanel.listModel.size()-1) 
      mainPanel.nextButton.setEnabled(false); 
     if (!current.isPlaying()) { 
      if (playlistPanel.listModel.size() > 1 && playlistPanel.listModel.indexOf(current) < playlistPanel.listModel.size()-1) { 
       current = (MP3) playlistPanel.listModel.get(playlistPanel.listModel.indexOf(current)+1); 
       playSong(current); 
      } 
      else 
       stopPlayback(); 
     } 
     else { 
      mainPanel.trackTimeLabel.setText(formatTime(trackTime)); 
      trackTime++; 
     } 
    } 
} 

public static void main(String[] args) throws Exception { 

    MP3Random instance = new MP3Random(); 
} 
} 

エラー:あなたが作業しているこのプロジェクトは、それらを使用しているため、すべての

Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException 
at java.lang.Thread.start(Thread.java:656) 
at pa2.MP3.play(MP3.java:41) 
at pa2.MP3Random.playSong(MP3Random.java:68) 
at pa2.MP3Random.access$4(MP3Random.java:62) 
at pa2.MP3Random$ButtonListener.actionPerformed(MP3Random.java:373) 
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028) 
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351) 
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387) 
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) 
at  javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236) 
at java.awt.Component.processMouseEvent(Component.java:6373) 
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) 
at java.awt.Component.processEvent(Component.java:6138) 
at java.awt.Container.processEvent(Container.java:2085) 
at java.awt.Component.dispatchEventImpl(Component.java:4735) 
at java.awt.Container.dispatchEventImpl(Container.java:2143) 
at java.awt.Component.dispatchEvent(Component.java:4565) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4621) 
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4282) 
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4212) 
at java.awt.Container.dispatchEventImpl(Container.java:2129) 
at java.awt.window.dispatchEventImpl(window.java:2478) 
at java.awt.Component.dispatchEvent(Component.java:4565) 
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:679) 
at java.awt.EventQueue.access$000(EventQueue.java:85) 
at java.awt.EventQueue$1.run(EventQueue.java:638) 
at java.awt.EventQueue$1.run(EventQueue.java:636) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) 
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) 
at java.awt.EventQueue$2.run(EventQueue.java:652) 
at java.awt.EventQueue$2.run(EventQueue.java:650) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:649) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) 

答えて

4

まず、あなたがスレッドに精通取得する必要があります!あなたのクラスの教科書はこのトピックをカバーするかもしれません。注意深く読んでください。スレッドは非常に重要です。あなたの教科書が明確でない場合は、read the official Java tutorialでもかまいません。

に戻るMP3クラスのすべてのインスタンスは別のスレッドで実行されます。 MP3スレッドはメインプログラムの実行(メインメソッドを実行するスレッドを意味する)とは別のもので、スイングUIは別のスレッドでも実行されます。あなたのエラーがjava.lang.IllegalThreadStateExceptionのJavadocを引用する、ことを示している

:ここ

a thread is not in an appropriate state for the requested operation. See, for example, the suspend and resume methods in class Thread.

を見ていくつかのものがあります:

  1. あなたのTimerクラスは、MP3のスレッドを停止して開始することができます。それはplaySong(現在)を呼び出します。およびstopPlayback()これらのメソッドを呼び出す別のクラスがありますか?あなたのエラーはユーザーイベントによって引き起こされました:pa2.MP3Random $ ButtonListener.actionPerformed(MP3Random.java:373) スレッドが再生準備が整う前にボタンをクリックしましたか?
  2. 一般に、2つのスレッドが互いに干渉しないようにする必要があります。古典的な例は、両方とも同じリストを変更する2つのスレッドです。 2番目のスレッドが(Iteratorを使用して、またはループごとに)リストを反復している間に、最初のスレッドがリストから項目を削除すると、例外がスローされます。
  3. GUIなしでmp3を再生するために指定されたクラスをテストできますか?ちょうど静的メソッド呼び出し。あなたはプレーヤーを働かせることができますか?

私の答えにあるポイント2はおそらくあなたの問題とは関係ありません。スレッドを扱うときには理解することが重要です。たとえば、PlaylistPanelで使用可能な曲のリストを変更する場合(複数のスレッドで変更できる場合)、そのクラスの一部を同期させる必要があります。これは、別のスレッドが同期メソッドを実行している場合にスレッドを強制的に待機させます。あなたの問題は、「デッド」であるスレッドを再起動しようとしているJavaDocs for Threadを見てください:

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

だからスレッドを開始するために、あなたが開始呼び出します。コールを開始します。そのスレッドは、run()が終了するまで他のスレッドと同時に実行されます。一度終了すると、そのスレッドが完了します。同じスレッドで複数の曲を再生したい場合は、この動作を実装する必要があります。しかし、あなたが投稿した実行方法(あなたが書いたことはないと思いますが、これはこの課題の一部として与えられました)はとてもシンプルです。 player.play();が呼び出され、palayが終了するとスレッドが終了します。

run()メソッドの最後の行は、player = nullでなければならないので、isPlaying()メソッドが正しく動作するようにしてください。

+0

こんにちはソーン、感謝を! ボタンを押した直後にエラーがポップアップします(最初のボタンは押されませんが、次/後ろの数回の停止開始クリックの後) 私は2点目を理解しています。コード内の深刻な問題をトラブルシューティングする方法がわかりません。 – Wangagat

+0

@Wangagat曲を再生する必要があるたびに新しいMP3インスタンスを作成していますか? – quaylar

+0

これは楽しい課題です。それはどんな授業ですか? – Thorn

2

ちょっと推測しますが、あなたのスレッドからAWT-Widgetsのメソッドを呼び出すことはできますか? SWTの場合、これはうまくいきません.Widget-Callは、GUIスレッド、つまりそれらを作成したスレッドから呼び出される必要があります。こののわからない はAWTでも同じですが、チェックするためにその価値...

+0

そうは思わない。最も可能性の高い答えは、既に言われたことです。ソングを再生する必要があるたびに、新しいmp3オブジェクトを作成する必要があります。コンパイルするコードを取得できませんでした。 MainPanelがJPanelを拡張し、 PlaylistPanelがJPanelを拡張します – Thorn

+0

@Thorn Correct、GETahの答えに関する私のコメントを参照してください。 – quaylar

7

問題はここにある:

public void play() { 
    try { 
    FileInputStream fis  = new FileInputStream(mp3_file); 
    BufferedInputStream bis = new BufferedInputStream(fis); 
    player = new Player(bis); 
    } 
    catch (Exception e) { 
    System.out.println("Problem playing file " + mp3_file); 
    System.out.println(e); 
    } 
    // run in new thread to play in background 
    start(); // <======== PROBLEM 
} 

Thread.Startjava doc氏は述べています:基本的に

Throws: IllegalThreadStateException - if the thread was already started.

、スレッドは複数回起動できません。 MP3.Play() によって開始されたMP3インスタンスでPlayを呼び出すたびに、この例外が発生します。MP3.Playが呼び出されるたびに、新しいトラックを作成してトラックを再生することをお勧めします。 プレイヤークラスは次のようになります。

public class MP3Player extends Thread { 
    public void PlayFile(String soundFile){ 
     //... Add player logic here 
    } 
    public void StopPlaying(){ 
     //.. Stop playing and gracefully exit this thread 
    } 
} 

そしてMP3のクラスで:助けを

public class MP3{ 
    MP3Player currentPlayer = null; 
    // ... 
    public void play() { 
     if(currentPlayer != null) currentPlayer.StopPlaying(); 
     currentPlayer = new MP3Player(); 
     currentPlayer.PlayFile(mp3_file); 
    } 
} 
+0

MP3インスタンスをMP3Random.playSong()メソッドに渡しているので、これは当てはまりません。あなたの理論が成立すれば、彼は毎回同じMP3インスタンスを渡さなければなりません... MP3は既にスレッドです! – quaylar

+0

バック/次/再生ボタンを押して以前に再生した曲を再生するとエラーが発生します。 私はmp3クラスを編集できないので、どうすればこのコードを修正できますか? – Wangagat

+0

@Wangagatそして、GETahが正しいです。曲を演奏するたびに、「MP3」クラスの新しいインスタンスを作成する必要があります。同じインスタンス上で 'MP3.play()'を何度も呼び出すので、既に開始されているスレッドを開始しようとしています。これは動作しません。 – quaylar

関連する問題