2013-07-19 2 views
1

방금 ​​Jlayer 라이브러리를 사용하여 MP3를 재생하기 시작했습니다. 그것은 완벽하게 작동하고 나는 노래를 재생할 수 있습니다. 내 유일한 문제는 일시 중지 및 다시 시작 메서드를 구현하는 것입니다. 나의 제한된 양의 멀티 스레딩에 대한 지식으로, 나는 MP3 대기를하는 스레드를 만드는 것이고 사운드는 멈출 것이고 노래를 다시 시작하기 위해서는 스레드에게 알릴 것입니다. 여기에 내가 무엇을 가지고있다 :JLayer 일시 중지 및 다시 시작

import java.util.Scanner; 

import java.io.BufferedInputStream; 
import java.io.FileInputStream; 

import javazoom.jl.player.Player; 

public class MP3 extends Thread{ 
    private String filename; 
    private Player player; 
    private Thread t; 
    private volatile boolean continuePlaying = true; 

    // constructor that takes the name of an MP3 file 
    public MP3(String filename) { 
     this.filename = filename; 
    } 

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

    // play the MP3 file to the sound card 
    public void play() { 
     try { 
      FileInputStream fis  = new FileInputStream(filename); 
      BufferedInputStream bis = new BufferedInputStream(fis); 
      player = new Player(bis); 
     } 

     catch (Exception e) { 
      System.out.println("Problem playing file " + filename); 
      System.out.println(e); 
     } 

    } 

    public void run() { 
     play(); 

      try { 
       while (true) { 
        synchronized(this) { 
        while(!continuePlaying) 
         wait(); 


        player.play(); 
        } 

       } 
      } 
      catch (Exception e) { 
       System.out.println(e); 

     } 

    } 



    private void pause() throws InterruptedException{ 

      System.out.println("Pause"); 
      continuePlaying = false; 



    } 

    private void resumeSong() throws InterruptedException{ 
     synchronized(this) { 
      System.out.println("Resume"); 
      continuePlaying = true; 
      notify(); 

     } 
    } 

    // test client 
    public static void main(String[] args) throws InterruptedException{ 
     String filename = ("Fall To Pieces.mp3"); 
     MP3 mp3 = new MP3(filename); 
     mp3.start(); 

     Scanner s = new Scanner(System.in); 
     s.nextLine(); 

     mp3.pause(); 

     s.nextLine(); 

     mp3.resumeSong(); 


     try { 
     mp3.join(); 
    } catch (Exception e){ 
    } 
    } 

} 

그러나 어떤 이유로 wait()는 아무 것도하지 않고 프로그램이 notify()에 도달하지도 않는다. 왜 이런 일이 일어나는 걸까요?

나는 이것에 대한 이전의 SO 질문을 읽었지만 제대로 작동하지 못했습니다. 또한 왜이 코드가 작동하지 않는지에 관심이 많아서 멀티 스레딩을 더 잘 이해할 수 있습니다. 고맙습니다!

+0

해결책은 여기에 있습니다. http://stackoverflow.com/questions/12057214/jlayer-pause-and-resume-song – pi4630

답변

0

내가 당신의 코드를 잘못 읽었다면 늦었습니다. 그러나 내가 보는 한, 당신은 continuePlaying = true;으로 스레드를 시작하고 run 메서드는 play();을 호출하지 않고 새로운 플레이어를 초기화하지 않고 점을 종료해야하는 while (true) 루프를 직접 입력합니다. continuePlaying은 그 스레드가 여전히 무한 루프에 갇혀 있으면 변경 될 수 없으며 휘발성 변수에 액세스하기 위해 다른 MP3 스레드를 시작하더라도 변경하기 전에 동일한 루프를 입력하게됩니다. 따라서 wait()에 도달하지 않습니다. 나중에 대기중인 스레드에 알리려고합니다(). 그것이 알려지기를 기다리고 있기 때문에 그리고 어떤 것도하지 않고 기다리는 상태에서 혼자만 알려주는 것이기 때문에 약간의 역설입니다. 통지를받을 때까지는 아무 것도 할 수 없습니다. 내가 말하고자하는 것은, wait()를 처리해야하지만 특히 adressed/waiting중인 스레드 외부에서 notify()를 처리해야한다는 것입니다.

또한 player.play();은 홀수 위치에 있습니다. 현재 플레이어는 while(!continuePlaying) 상태 뒤에 있기 때문에 스레드가 적어도 한 번 일시 중지 (대기) 된 후에 재생을 시작해야합니다.

그래서 당신의 경우에는 wait() 및 notify()를 호출하고 문제의 스레드를 동기화하여 다른 스레드 (또는 테스트의 주 스레드)에있는 메서드를 사용하는 것이 좋습니다.

+0

아, 알겠습니다. 이것은 스레드를 사용하여 처음으로 당신이 옳은 것 같아요. 그러나, 내 질문에 어떻게 while 루프를 사용하지 않고 스레드가 살아있을 유지할 수 있습니다? 또한 부울을 변경할 수 없다면 스레드를 일시적으로 일시 중단 할 수 있습니까? – amb110395

+1

@ amb110395 왜 스레드 내의 변수에 따라 스레드를 일시 중단 하시겠습니까? mp3.wait();을 호출하는 것에 대해 아무 말도하지 않습니다. mp3.pause() 대신 알림 (중간에 동기화 유지)과 동일합니까? 더 나아가 스레드를 유지하기 위해 영구 루프가 필요하지 않습니다. 다른 객체와 마찬가지로 변수가 mp3 인 액티브 참조가있는 한 괜찮습니다. – Akunosh

+0

그래, 비슷한 것을했는데 효과가있었습니다. 어쨌든 고맙습니다. – amb110395