I am trying to play an mp3 file on button press or selection from a list (which I have managed successfully). However, I cannot seem to stop the song being played multiple times on the same button press.
What I would like to do is play the song in a new thread, disable playing the song again until the thread has closed, then allow playing again.
My code is as follows:
public class SoundFactory {
private Player player;
private static boolean running = false;
private String getFile(String name) {
String f = "sound" + File.separator + name + ".mp3";
return f;
}
public void playMP3(String name) {
if (!running) {
running = true;
try {
FileInputStream fis = new FileInputStream(getFile(name));
BufferedInputStream bis = new BufferedInputStream(fis);
player = new Player(bis);
} catch (Exception e) {
System.out.println("Problem playing file " + name);
System.out.println(e);
}
// run in new thread to play in background
new Thread() {
public void run() {
try {
player.play();
} catch (Exception e) {
System.out.println(e);
}
}
}.start();
//running = false;
}
}
public void close() {
if (player != null) player.close();
}
}
The file is played via:
SoundFactory sf = new SoundFactory();
sf.playMp3("song name");
on a JButton click
I am new to threading so I apologise in advance if this has an obvious solution!
It sounds to me like you are getting multiple click events fired at once instead of just one. A little logging should verify this. Your method as is, is wide open to race conditions.
The two events can be so close together that when the one checks running it see !running as true. Before that one can do running = true, the second event also sees !running as true and enters the if clause. They then both set running to true and spawn a thread to play the mp3.
What you need to do is make your method synchronized.
public synchronized void playMP3(String name)
http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
If count is an instance of SynchronizedCounter, then making these
methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing
a synchronized method for an object, all other threads that invoke
synchronized methods for the same object block (suspend execution)
until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent
invocation of a synchronized method for the same object. This
guarantees that changes to the state of the object are visible to all
threads.
Just to clarify my last comment, here is a test program showing where running = false should be placed.
public class Test {
public static boolean running = false;
public synchronized void runner() {
if(!running) {
running = true;
System.out.println("I'm running!");
new Thread() {
public void run() {
for(int i=0; i<10000; i++) {} // Waste some time
running = false; // This is only changed once the thread completes its execution.
}
}.start();
} else {
System.out.println("Already running.");
}
}
public static void main(String[] args) {
Test tester = new Test();
tester.runner();
tester.runner(); // The loop inside the Thread should still be running so this should fail.
for(int i=0; i<20000; i++) {} // Waste even more time.
tester.runner(); // The loop inside the Thread should be done so this will work.
}
}
It outputs:
I'm running!
Already running.
I'm running!
It's been years since I've worked with Swing and had forgotten that its event dispatcher is single threaded. So your issue is more likely this than a race condition. It still doesn't hurt to get into writing things to be thread safe from the beginning as it gets you used to it and thinking that way.
Definite warning on using the synchronized method... It can be horrible on performance if only a small part of your method needs to be synchronized. In this case your whole method needs to be thread safe.
If only a small part needs to be thread safe you need to use synchronized blocks.
Thread safe per instance:
public class myClass {
public void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(this) {
// Code that needs to be thread safe per instance
}
// More code that doesn't need thread safety.
}
}
Thread safe across all instances.
public class myClass {
static Object lock = new Object();
public void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(lock) {
// Code that needs to be thread safe across all instances.
}
// More code that doesn't need thread safety.
}
}
Thread safe in a static method.
public class myClass {
public static void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(MyClass.class) {
// Code that needs to be thread safe.
}
// More code that doesn't need thread safety.
}
}
Probably way more information than you want, but I've just seen threaded programming taught so poorly many, many times.
You need to call JButton.setEnabled(false); right before you start playing the mp3, and then call JButton.setEnabled(true); when the mp3 finishes playing.
Obviously, you should replace JButton with your button's object (eg: playButton.setEnabled()).
Related
I have what I thought was a simple problem, which I have yet to find a good solution to: I would like to be able to pause and unpause the activity taking place in a thread, by hitting a button on a Swing interface panel.
Specifically, I would like to use one thread to take in audio frames in real time; a second thread to perform magic processing on those frames; and a third thread to serialize the results and send over a socket somewhere else. The kicker is that depending on the brand of magic we employ, the processing in the second thread might take longer per frame to perform than the actual data collection, and the data might pile up after a while.
As a very crude prototype workaround we thought we'd add a GUI with a button to turn the audio collection process on and off and a status bar (to be implemented later) so that a user could sort of keep an eye on how full the buffer (a linked blocking queue) happened to be.
This is harder than I anticipated. I've stripped the problem down to a toy version: A linked blocking queue that can store 50 Integers, a GUI, two threads (adding to and removing from the queue at different rates) and a Token object wrapped around a boolean. It looks like this, and it sorta works:
Test.java
public class Test {
public static void main(String[] args) throws IOException {
Token t1 = new Token();
Token t2 = new Token();
LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<Integer>(50);
startFill sf = new startFill(t1, lbq);
startEmpty se = new startEmpty(t2, lbq);
TestUI testUI = new TestUI(t1, t2, lbq);
testUI.setVisible(true);
sf.start();
se.start();
}
}
TestUI.java
public class TestUI extends JFrame implements ActionListener {
private JToggleButton fillStatus, emptyStatus;
public boolean filling, emptying;
public Token t1, t2;
public LinkedBlockingQueue<Integer> lbq;
public TestUI(Token t1, Token t2, LinkedBlockingQueue<Integer> lbq) {
this.t1 = t1;
this.t2 = t2;
this.lbq = lbq;
initUI();
}
public synchronized void initUI() {
JPanel panel = new JPanel();
panel.setLayout(null);
filling = false;
fillStatus = new JToggleButton("Not Filling");
fillStatus.setBounds(20, 20, 150, 25);
fillStatus.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (filling == false) {
fillStatus.setText("Filling");
} else {
fillStatus.setText("Not Filling");
}
filling = !filling;
t1.flip();
System.out.println("fill button press");
}
});
// Similar code for actionListener on Empty button, omitted
panel.add(fillStatus);
panel.add(emptyStatus);
add(panel);
setTitle("Test interface");
setSize(420, 300);
setLocationByPlatform(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
}
}
startFill.java
public class startFill extends Thread {
public Token token;
public LinkedBlockingQueue<Integer> lbq;
public startFill(Token token, LinkedBlockingQueue<Integer> lbq) {
this.token = token;
this.lbq = lbq;
}
public void run() {
int count = 0;
while (true) {
while (!token.running()) {
try {
sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (token.running()) {
try {
lbq.put(count);
System.out.println("queue size = " + lbq.size());
count++;
sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
}
There is also a startEmpty.java that works about the same way, and a Token.java that's a wrapper for a boolean state variable, omitted for merciful brevity.
So that works, but at the expense of polling in the while (!token.running()) loop.
I tried using Locks and Conditions, but failed, always getting IllegalMonitorStateExceptions.
And I looked at this similar question and managed to get that working, but at the expense of using the yield() method which apparently differs significantly between Java 5 and Java 6, and seems to be highly discouraged.
So my question: Is there some correct, or significantly better way to do what I am trying to do? It seems like there should be a way to make this happen without the polling and with reliable methods.
Update: I'm not sure I can get around the issue of controlling the audio capture loop in some way for the application. Whether it is a human pressing a button, or internal logic making decisions based on some other factors, we really need to be able to shut the darn thing down and bring it back to life on command.
Instead of handling the synchronisation between your 3 worker processes by hand via a GUI, you could also setup a factory lineup between the workers:
add 2 queues between your workers
block your threads on queue-state conditions;
readers (consumers) block on empty queue
writers (producers) block when the queue is full (say 2n messages where n is the number of consumers for that queue.)
wait() on a queue to block your thread and notifyAll() on that queue after adding or removing a message from a queue.
A setup like this automatically slows down producers running faster than their consumers.
Why dont you implement ArrayBlockingQueue.
Its Better use ArrayBlockingQueue class which is present in java.util.concurrent package, which is Thread Safe.
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(100);
Here is one way to do what I was trying to do: Properly use wait() and notify(), synchronized on the Token objects, like such:
startFill.java run() method
public synchronized void run() {
int count = 0;
try {
// token initializes false
// wait until notification on button press
synchronized (token) {
token.wait();
}
// outer loop
while (true) {
// inner loop runs as long as token value is true
// will change to false on button press
while (token.running()) {
lbq.put(count);
System.out.println("queue size = " + lbq.size());
count++;
sleep(100);
}
// wait until notification on button press, again
synchronized (token) {
token.wait();
}
}
} catch (InterruptedException e2) {
e2.printStackTrace();
}
}
TestUI.java ActionListener:
fillStatus.addActionListener(new ActionListener() {
// t1 was initialized false
public void actionPerformed(ActionEvent event) {
if (filling == false) {
fillStatus.setText("Filling");
// if false, change t1 status to true
t1.flip();
// and send the notification to the startFill thread that it has changed
synchronized (t1) {
t1.notify();
}
} else {
fillStatus.setText("Not Filling");
// if true, change t1 status to false
t1.flip();
// no notification required due to polling nature of startFill's active thread
}
filling = !filling;
System.out.println("fill button press");
}
});
This works rather nicely, without polling while the thread is turned off.
My initial attempts at this failed due to bad syntax-- I neglected the synchronized (token) {...} context block around the wait() and notify() statements.
I have a certain function in my program that I want to stop on the press of a key. I have a native keyboard hook set up for that purpose. Right now, I call System.exit(0) when that key is detected. However, I don't want to exit the program, just stop that operation and return to where it was called. An example is given below.
public class Main {
public static void main(String[] args) {
System.out.println("Calling function that can be stopped with CTRL+C");
foo(); // Should return when CTRL+C is pressed
System.out.println("Function has returned");
}
}
I've tried putting the call to foo() in a thread so I could call Thread.interrupt() but I want the function call to be blocking, not non-blocking. Also there are blocking IO calls in foo() so I'd rather not deal with interrupts unless it's necessary, because I'd have to deal with ClosedByInterruptException exceptions and that has caused problems before.
Also the body of foo() is very long and has many function calls inside it, so writing if (stop == true) return; in the function is not an option.
Is there a better way to do this than making a blocking thread? If so, how? If not, how would I make a blocking thread?
How about this?
// Create and start the thread
MyThread thread = new MyThread();
thread.start();
while (true) {
// Do work
// Pause the thread
synchronized (thread) {
thread.pleaseWait = true;
}
// Do work
// Resume the thread
synchronized (thread) {
thread.pleaseWait = false;
thread.notify();
}
// Do work
}
class MyThread extends Thread {
boolean pleaseWait = false;
// This method is called when the thread runs
public void run() {
while (true) {
// Do work
// Check if should wait
synchronized (this) {
while (pleaseWait) {
try {
wait();
} catch (Exception e) {
}
}
}
// Do work
}
}
}
(taken from http://www.exampledepot.com/egs/java.lang/PauseThread.html not my own work)
I have a Java book I'm learning from and in one of the examples, I saw something suspicious.
public class ThreadExample extends MIDlet {
boolean threadsRunning = true; // Flag stopping the threads
ThreadTest thr1;
ThreadTest thr2;
private class ThreadTest extends Thread {
int loops;
public ThreadTest(int waitingTime) {
loops = waitTime;
}
public void run() {
for (int i = 1; i <= loops; i++) {
if (threadsRunning != true) { // here threadsRunning is tested
return;
}
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
}
public ThreadExample() {
thr1 = new ThreadTest(2);
thr2 = new ThreadTest(6);
}
public void startApp() throws MIDletStateChangeException {
thr1.start();
thr2.start();
try {
Thread.sleep(4000); // we wait 4 secs before stopping the threads -
// this way one of the threads is supposed to finish by itself
} catch(InterruptedException e) {
System.out.println(e);
}
destroyApp();
}
public void destroyApp() {
threadsRunning = false;
try {
thr1.join();
thr2.join();
} catch(InterruptedException e) {
System.out.println(e);
}
notifyDestroyed();
}
}
As it is a MIDlet app, when it's started, the startApp method is executed. To keep it simple, the startApp method itself calls destroyApp and so the program destroys, stopping the threads and notifying the destruction.
The question is, is it safe to use this 'threadsRunning' variable and would its use inside both threads and in the destroyApp method cause any trouble at some point? Would 'volatile' keyword put in front of the declaration help to synchronize it?
Setting a boolean value is atomic, and there is no "read then modify" logic in this example, so access to the variable doesn't need to be synchronised in this particular case.
However, the variable should at least be marked volatile.
Marking the variable volatile does not synchronise the threads' access to it; it makes sure that a thread doesn't miss another thread's update to the variable due to code optimisation or value caching. For example, without volatile, the code inside run() may read the threadsRunning value just once at the beginning, cache the value, and then use this cached value in the if statement every time, rather than reading the variable again from main memory. If the threadsRunning value gets changed by another thread, it might not get picked up.
In general, if you use a variable from multiple threads, and its access is not synchronised, you should mark it volatile.
I'm using a thread that is continuously reading from a queue.
Something like:
public void run() {
Object obj;
while(true) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
What is the best way to stop this thread?
I see two options:
1 - Since Thread.stop() is deprecated, I can implement a stopThisThread() method that uses a n atomic check-condition variable.
2 - Send a Death Event object or something like that to the queue. When the thread fetches a death event, it exits.
I prefer the 1st way, however, I don't know when to call the stopThisThread() method, as something might be on it's way to the queue and the stop signal can arrive first (not desirable).
Any suggestions?
The DeathEvent (or as it is often call, "poison pill") approach works well if you need to complete all of the work on the queue before shutting down. The problem is that this could take a long time.
If you want to stop as soon as possible, I suggest you do this
BlockingQueue<O> queue = ...
...
public void run() {
try {
// The following test is necessary to get fast interrupts. If
// it is replaced with 'true', the queue will be drained before
// the interrupt is noticed. (Thanks Tim)
while (!Thread.interrupted()) {
O obj = queue.take();
doSomething(obj);
}
} catch (InterruptedException ex) {
// We are done.
}
}
To stop the thread t that instantiated with that run method, simply call t.interrupt();.
If you compare the code above with other answers, you will notice how using a BlockingQueue and Thread.interrupt() simplifies the solution.
I would also claim that an extra stop flag is unnecessary, and in the big picture, potentially harmful. A well-behaved worker thread should respect an interrupt. An unexpected interrupt simply means that the worker is being run in a context that the original programmer did not anticipate. The best thing is if the worker to does what it is told to do ... i.e. it should stop ... whether or not this fits with the original programmer's conception.
Why not use a scheduler which you simply can stop when required? The standard scheduler supports repeated scheduling which also waits for the worker thread to finish before rescheduling a new run.
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(myThread, 1, 10, TimeUnit.SECONDS);
this sample would run your thread with a delay of 10 sec, that means when one run finishes, it restarts it 10 seconds later. And instead of having to reinvent the wheel you get
service.shutdown()
the while(true) is not necessary anymore.
ScheduledExecutorService Javadoc
In your reader thread have a boolean variable stop. When you wish for this thread to stop set thius to true and interrupt the thread. Within the reader thread when safe (when you don't have an unprocessed object) check the status of the stop variable and return out of the loop if set. as per below.
public class readerThread extends Thread{
private volitile boolean stop = false;
public void stopSoon(){
stop = true;
this.interrupt();
}
public void run() {
Object obj;
while(true) {
if(stop){
return;
}
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(stop){
return;
}
obj = objectesQueue.poll();
// Do something with the Object obj
}
}
}
}
public class OtherClass{
ThreadReader reader;
private void start(){
reader = ...;
reader.start();
}
private void stop(){
reader.stopSoon();
reader.join(); // Wait for thread to stop if nessasery.
}
}
Approach 1 is the preferred one.
Simply set a volatile stop field to true and call interrupt() on the running thread. This will force any I/O methods that wait to return with an InterruptedException (and if your library is written correctly this will be handled gracefully).
I think your two cases actually exhibit the same potential behavior. For the second case consider Thread A adds the DeathEvent after which Thread B adds a FooEvent. When your job Thread receives the DeathEvent there is still a FooEvent behind it, which is the same scenario you are describing in Option 1, unless you try to clear the queue before returning, but then you are essentially keeping the thread alive, when what you are trying to do is stop it.
I agree with you that the first option is more desirable. A potential solution would depend on how your queue is populated. If it is a part of your work thread class you could have your stopThisThread() method set a flag that would return an appropriate value (or throw Exception) from the enqueuing call i.e.:
MyThread extends Thread{
boolean running = true;
public void run(){
while(running){
try{
//process queue...
}catch(InterruptedExcpetion e){
...
}
}
}
public void stopThisThread(){
running = false;
interrupt();
}
public boolean enqueue(Object o){
if(!running){
return false;
OR
throw new ThreadNotRunningException();
}
queue.add(o);
return true;
}
}
It would then be the responsibility of the object attempting to enqueue the Event to deal with it appropriately, but at the least it will know that the event is not in the queue, and will not be processed.
I usually put a flag in the class that has the Thread in it and in my Thread code I would do. (NOTE: Instead of while(true) I do while(flag))
Then create a method in the class to set the flag to false;
private volatile bool flag = true;
public void stopThread()
{
flag = false;
}
public void run() {
Object obj;
while(flag) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class looks like :
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations() can be pretty long to run, so while it is running the old translations are still available. This is done by loading the translations in a local Map and just changing the reference when all translations are loaded.
My problem is : how do I make sure that when a thread is already loading translations, is a second one also tries to run, it detects that and returns immediately, without starting a second update.
A synchronized method will only queue the loads ... I'm still on Java 1.4, so no java.util.concurrent.
Thanks for your help !
Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:
/**
* #author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
Test code that will throw an exception if the task runs concurrently:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}
I am from a .net background(no java experience at all), but you could try a simple static flag of some sort that checks at the beginning of the method if its alrady running. Then all you need to do is make sure any read/write of that flag is synchronized. So at beginning check the flag, if its not set, set it, if it is set, return. If its not set, run the rest of the method, and after its complete, unset it. Just make sure to put the code in a try/finally and the flag iunsetting in the finally so it always gets unset in case of error. Very simplified but may be all you need.
Edit: This actually probably works better than synchronizing the method. Because do you really need a new translation immediately after the one before it finishes? And you may not want to lock up a thread for too long if it has to wait a while.
Keep a handle on the load thread to see if it's running?
Or can't you just use a synchronized flag to indicate if a load is in progress?
This is actually identical to the code that is required to manage the construction of a Singleton (gasp!) when done the classical way:
if (instance == null) {
synchronized {
if (instance == null) {
instance = new SomeClass();
}
}
}
The inner test is identical to the outer test. The outer test is so that we dont routinely enter a synchronised block, the inner test is to confirm that the situation has not changed since we last made the test (the thread could have been preempted before entering Synchronized).
In your case:
if (translationsNeedLoading()) {
synchronized {
if (translationsNeedLoading()) {
loadTranslations();
}
}
}
UPDATE: This way of constructing a singleton will not work reliably under your JDK1.4. For explanation see here. However I think you are you will be OK in this scenario.