Using boolean var for stopping threads - java

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.

Related

Synchronized block still locked after thread restart

I try to restart thread but synchronized block in thread keep locked after restarted. I shouldn't change socket properties because some processes take too long but when network connection lost it hangs forever. I try to use InterruptedException but it doesn't work. Is there any way to release this lock?
public static void main(String[] args) {
try {
synchronizedBlock t1 = new synchronizedBlock();
t1.start();
Thread.sleep(500);
t1.cancel();
t1 = new synchronizedBlock();
t1.start();
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
}
}
public class synchronizedBlock extends Thread {
boolean isRunning = true;
boolean isRunning2 = true;
public static Object[] locks = new Object[5];
public synchronizedBlock() {
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
}
public void cancel() {
isRunning = false;
interrupt();
}
public void socketProces() {
while (isRunning2) {
}
}
public void proces(int index) {
try {
synchronized (locks[index]) {
System.out.println("Synchronized Block Begin");
socketProces();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
System.out.println("Run begin");
while (isRunning) {
proces(1);
}
Thread.sleep(1);
} catch (InterruptedException e) {
//Do Something
} catch (Exception e) {
e.printStackTrace();
}
}
}
Result:
Run begin
Synchronized Block Begin
Run begin
When you start the synchronizedBlock thread you'll get a stack trace like this I think:
run -> proces -> socketProcess.
Then because isRunning2 = true, the thread will enter an infinite loop in socketProcess and never terminate.
Keep in mind that in Java there is no such thing as 'restarting' a thread. Once started, a thread can never be restarted. Indeed, you are creating two sycnchronizedBlock objects, not restarting a single object.
As a side note, it is generally problematic to overwrite static state in a class constructor, as you're doing with the locks variable, without synchronization.
The issue here is the Integer cache which is used in the for loop to initialize the synchronizedBlock.locks array:
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
When this code is run again, due to the constructor of the second synchronizedBlock, the synchronizedBlock.locks array contains the same Integer instances which where created when this for loop was executed for the first time. This means that the synchronized (locks[index]) lock will be on the same Integer object. As you have already one thread holding the lock for the Integer(1) object, the second thread waits outside the lock waiting for it to be released.
This is also problematic in combination with the fact that the first thread is not terminating. Your method
public void socketProces() {
while (isRunning2) {
}
}
is an endless loop as you don't change the value of isRunning2, ever. Also, the interrupt() method itself does not stop any thread. Instead, it sets just an internal flag in the Thread class, which can be checked with isInterrupted() and interrupted(). You have to check this flag and react on it like "Oh, someone wants me to stop, so I stop now".
To solve your problem you should at least quit your thread when the "isInterrupted" flag of the Thread instance is set. You can do it like this:
public void socketProces() {
while (isRunning2) {
if (Thread.interrupted()) {
return;
}
}
}
Instead of returning from socketProces() normally you could throw an InterruptedException like other methods do.
Also, depending on how you want to initialize/use the instances you want to lock on with synchronized(...), you might want to consider on how you create/fill the synchronizedBlock.locks array and which objects you want to use (the Integer cache might be problematic here). It depends on you if the creation of a new synchronizedBlock instance will/should/shouldn't create new objects to lock on in the synchronizedBlock.locks array.

How do I stop mp3 files being played multiple times at once?

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()).

Synchronized functions in Java

I have a class with a function which is synchronized like so:
public synchronized void enqueue(int number) {...}
In my program I have several threads running all wanting to use this function on a specific object of the class. What I would like to happen is for the threads to simply try using the function and if it is locked to not wait on it simply skip running that function.
Can this be done without using the Java.util.concurency library and only using syncronization primatives?
The restriction of not using concurrency is not optional
I like the AtomicInteger solution, but of course AtomicInteger is part of the concurrency package. You can follow the same principle (with lower efficiency, though) with the following simple code:
private boolean locked = false;
public void enqueue(int number) {
synchronized (this) {
if (locked) {
return;
}
locked = true;
}
try {
// Synchronized goodness goes here.
} finally {
synchronized (this) {
locked = false;
}
}
}
Since you're restricted here, here's what I would do:
Make a class with the ability to tell it that you want to lock on it. There are two types of locks: passive lock, and active lock. A passive lock will allow an unlimited number of threads to pass. An active lock will make it belong only to that thread.
When you want a passive lock, you have to register yourself, and unregister yourself when you're done. You'll wait on an internal object until all active locks are done.
When you want an active lock, you wait for all current passive locks have unregistered. If there's currently an active lock (store a thread reference to see if there is, utilizing Thread.currentThread()) then wait until notified. You can then set yourself as the referred thread. When you unregister, if there are waiting active locks, notify one of them (consider a Set<Thread> to register this). If there aren't, notify all the passive locks that are waiting and they can go through.
There's going to be a lot of unanswered questions here, and I doubt it's perfect, but this is most of what you're looking for...
Rather than use any synchronization primitives I'd recommend using something like the AtomicInteger class to leverage a CAS (compare-and-swap) operation for your anti-concurrency strategy:
public void enqueue(int number) {
if (!atomicInteger.compareAndSet(0, 1) {
return;
}
try {
// Synchronized goodness goes here.
} finally {
atomicInteger.set(0);
}
}
May be you can you synchronize the object that handles the Queue. If someone else ois using the queue the enqueue does nothing. I have an example that compiles and run. Very simple example but not pretty:
class Queue {
public void enqueue(int number) {
// something in this method for demo purposes only
try {
Thread.sleep(100);
} catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+" done");
}
}
class Demo {
private static Queue e = new Queue();
public void enqueue(int number) {
Queue q = getQueue();
if (q!=null) {
q.enqueue(number);
releaseQueue(q);
} else {
// do nothing since the queue is being used
System.out.println(Thread.currentThread().getName()+" done doing nothing");
}
}
public synchronized Queue getQueue() {
Queue b = e;
e = null;
return b;
}
public synchronized void releaseQueue(Queue q) {
e = q;
}
public static void main(String[] args) {
for (int j = 0; j < 5; j++) {
Thread t = new Thread(new Runnable() {
public void run() {
Demo d = new Demo();
d.enqueue(5);
}
}, "Thread "+j);
t.start();
try {
Thread.sleep(50);
} catch (InterruptedException e){}
}
}
}
YES You can implement locking on your own by managing a static variable in that class, or a using a "lock" text file, for example.
HOWEVER Although this simplistic hack would not be terribly difficult --- the java.util.concurrency package solution would be EVEN EASIER, AND is a better choice because, as you will quickly find, when building multithreaded resources into applications our needs will quickly exceed your current expectations
Don't worry about the WHOLE concurrency package -- I find that just taking 3 minutes to learn how to use the AtomicBoolean or AtomicLong fields can be enough to enable simple, multithreaded logic with a minimal effort.

Stopping looping thread in Java

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

Java 1.4 synchronization: only allow one instance of method to run (non blocking)?

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.

Categories

Resources