我刚开始使用Jlayer库播放MP3。它完美无缺,我可以播放这首歌。我唯一的问题是实现暂停和恢复方法。由于我对多线程的知识有限,我虽然制作了播放MP3的线程等待,声音会停止,为了恢复歌曲,我只需要通知线程。这是我得到的:
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 :(得分:0)
现在已经很晚了,如果我错误地读了你的代码,请原谅我。但据我所知,你用continuePlaying = true;
启动你的线程,run方法只调用play();
没有初始化新玩家然后直接进入while (true)
循环必须退出点。 continuePlaying不能被那个仍然停留在它的无限循环中的线程改变,即使你启动另一个MP3线程来访问volatile变量,它也会在能够改变任何东西之前进入同一个循环。因此永远不会达到wait()。
稍后,您试图从内部通知()您的等待线程。这有点矛盾,因为它等待被通知并处于等待无所事事的状态,更不用说通知自己了。在通知之前,它根本无法做任何事情,包括通知自己或他人。我想说的是,你应该处理wait(),尤其是来自正在被压缩/等待的线程外部的notify()。
此外,您的player.play();
处于奇怪位置。此时播放器应该仅在线程暂停(等待)至少一次之后才开始播放,因为它位于while(!continuePlaying)
条件之后。
因此,对于您的情况,我会使用不同线程(甚至是测试的主线程)中的方法来调用wait()和notify()并在相关线程上进行同步。