1

I just started using the Jlayer library to play MP3s. It works perfectly and I can play the song. My only problem is implementing pause and resume methods. With my limited amount of knowledge about multithreading, I though that making the thread where I play the MP3 wait, the sound would stop and in order to resume the song I would just have to notify the thread. Here is what I got:

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){
    }
    }

}

For some reason, however, wait() doesn't do anything and the program doesn't even reach notify(). Why is this happening?

I've read the previous SO questions about this, but I haven't been able to make them work. I am also interested in learning why this code doesn't work so I can further understand multithreading. Thank you!

amb110395
  • 1,545
  • 13
  • 16

1 Answers1

0

It's late here so pardon me if I read your code wrong. But as far as I see it, you start your thread with continuePlaying = true; and the run method just calls play(); no initialize the new player and then straight enters a while (true) loop wich has to exit point. continuePlaying can't be changed by that thread still stuck in it's endless loop and even if you start another MP3 thread to access the volatile variable, it will enter the same loop before being able to change anything. Therefore wait() will never be reached. Later on you are trying to notify() your waiting thread from within itself. Which is a bit of a paradoxon because it is waiting to be notified and in that state of waiting doing nothing, let alone notifying itself. It simply can't do anything until notified, that includes notifying itself or others. What I am trying to say is, that you should handle wait() but especially notify() from outside the thread that is being adressed/waiting.

Additionally your player.play(); is in an odd position. At the moment the player should only start playing after the thread has been paused(waited) at least once because it is behind the while(!continuePlaying) condition.

So for your case i'd rater go with methods in a different thread (or even the main thread for your tests) which call a wait() and notify() on and synchronized over the thread in question.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Akunosh
  • 237
  • 1
  • 2
  • 10
  • Oh I see. This is my first time using threads so I guess you are right. However, my question is how can I keep thread the alive without using the while loop? Also, how can I temporarily suspend the thread if I can never change the boolean? – amb110395 Jul 21 '13 at 01:21
  • 1
    @amb110395 Why do you want to suspend your thread depending on a variable inside that thread? Is anything speaking against calling mp3.wait(); instead of mp3.pause() and same with notify (keeping synchronization in mid with those)? Further more you don't need a permanent loop to keep your thread alive. Like any other object it should be fine as long as it got an active reference, which it got as the variable mp3.. – Akunosh Jul 22 '13 at 10:44
  • Yeah, I did something similar to that and it worked. Thank you anyways – amb110395 Jul 22 '13 at 15:13