Why does this simple threaded program get stuck? - java

Take a look at this simple Java program:
import java.lang.*;
class A {
static boolean done;
public static void main(String args[]) {
done = false;
new Thread() {
public void run() {
try {
Thread.sleep(1000); // dummy work load
} catch (Exception e) {
done = true;
}
done = true;
}
}.start();
while (!done);
System.out.println("bye");
}
}
On one machine, it prints "bye" and exits right away, while on another machine, it doesn't print anything and sits there forever. Why?

This is because your boolean is not volatile, therefore Threads are allowed to cache copies of it and never update them. I would recommend an AtomicBoolean - that will prevent any issues you may have.
public static void main(String args[]) {
final AtomicBoolean done = new AtomicBoolean(false);
new Thread() {
public void run() {
done.set(true);
}
}.start();
while (!done.get());
System.out.println("bye");
}

By the time the main program's while loop is reached (which is also a Thread), the new Thread might be finishing its run() where done flag is set to true. Just to confirm this, you can add a sleep in the run() before done is set to true and then see if your bye is displayed on other machine also. Hope this would help.

Related

Thread is not stopping properly

I'm new to java concurrent coding and encounter an issue. The following code cannot stop while it runs. Who can tell me why? Thanks
import java.util.concurrent.TimeUnit;
public class Test {
private static boolean stop;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
System.out.println(Thread.currentThread());
System.out.println(stop);
while (!stop) {
}
}).start();
TimeUnit.SECONDS.sleep(1);
stop = true;
System.out.println(Thread.currentThread());
System.out.println(stop);
}
}
I also try to run the following code and it can stop. Who can tell me why? Thanks
import java.util.concurrent.TimeUnit;
public class Test {
private static boolean stop;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
System.out.println(Thread.currentThread());
System.out.println(stop);
while (!stop) {
System.out.println(" ");
}
}).start();
TimeUnit.SECONDS.sleep(1);
stop = true;
System.out.println(Thread.currentThread());
System.out.println(stop);
}
}
Because you've not indicated to the compiler that stop might be changed and read by multiple threads:
private static boolean stop;
it is allowed to optimize this:
while (!stop) {
}
to
if (!stop) {
while (true) {
}
}
which will never stop if stop is initially false.
Declaring stop volatile:
private static volatile boolean stop;
disallows this optimization.
JVM typically optimizes your code before actually executing it. In your case, while(!stop){} gets optimized to while(true){}. This happens because you aren't explicitly accessing your static variable via synchronized function, and JVM assumes the variable won't change in Thread unsafe manner.
To avoid the optimization, place anything in your while loop. You could do something like:
while(!stop) {
try{
Thread.sleep(1); // You could also call any other function here.
}
catch(Exception e) { }
}
In this case, JVM wouldn't try to optimize, and your code will execute as expected.
EDIT:
While this does work currently, but based on comments, I concur that this can change in future versions (or in other parallel implementations of JDK/JVM). Declaring the variable as volatile is the best way to avoid that optimization.

What should I be doing to stop the thread execution?

import java.lang.Thread;
import java.util.Scanner;
class Running extends Thread{
private boolean Run=true;
public void shutdown(){
Run=false;
}
public void run(){
while(Run){
for(int i=0;i<1000;i++){
System.out.println("Starting Counter:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Volatile {
public static void main(String[] args) {
Running run1=new Running();
run1.start();
System.out.println("Press any key to stop thread execution");
Scanner sc=new Scanner(System.in);
sc.nextLine();
run1.shutdown();
}
}
I am using a volatile key word to stop the thread execution. But couldn't get the solution
What should I be doing to stop the thread execution?
So your post mentions the volatile keyword but I don't see it in the code you've posted. You need to make sure that Run is a volatile boolean so that it can be changed in the main thread and the other thread will see the changes.
private volatile boolean Run=true;
But I think the problem is that you are testing for this Run only in the outer while loop. Maybe you want it also in the inner counting loop. Something like:
for(int i = 0; i < 1000 && Run; i++) {
Right now, once the loop start counting it will have to finish before the Run boolean is checked. That may be 1000 seconds in the future.
You are using the right pattern, but apply it a bit wrong:
Your Runflag will only be checked after 1000 seconds, because it will only be checked after the for loop finished. Change your code to the following:
public void run(){
while(Run){
for(int i=0;(i<1000) && (Run == true);i++){
System.out.println("Starting Counter:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Please note you will have to completely remove the while loop if you don't want your for loop to be executed endlessly effectively.
A time ago the thread was stopped simply by calling the Thread's stop() function. Nowadays, it's deprecated because it's unsecure, so you have to stop the Thread from the inside of the Thread. You'll find a good example here. Keep in mind that doing this doesn't stop immediately the thread, it just tells it's available for stopping and Android will stop it whenever it finds it necessary.
Your code stays in the for-loop for 1000 seconds until it finally reaches the while(run) branch again. I guess this is why its not working properly.
These is the sample .You can create a boolean field and check it inside run:
public class Sample implements Runnable {
private volatile boolean isRunning = true;
public void run() {
while (isRunning) {
//do work
}
}
public void kill() {
isRunning = false;
}
}
To stop it just call
sample.kill();
This should work.

Alternative method to kill thread

I have been looking for ways to kill a thread and it appears this is the most popular approach
public class UsingFlagToShutdownThread extends Thread {
private boolean running = true;
public void run() {
while (running) {
System.out.print(".");
System.out.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
System.out.println("Shutting down thread");
}
public void shutdown() {
running = false;
}
public static void main(String[] args)
throws InterruptedException {
UsingFlagToShutdownThread t = new UsingFlagToShutdownThread();
t.start();
Thread.sleep(5000);
t.shutdown();
}
}
However, if in the while loop we spawn another another object which gets populated with data (say a gui that is running and updating) then how do we call back - especially considering this method might have been called several times so we have many threads with while (running) then changing the flag for one would change it for everyone?
thanks
One approach with these problems is to have a Monitor class which handles all the threads. It can start all necessary threads (possibly at different times/when necessary) and once you want to shutdown you can call a shutdown method there which interrupt all (or some) of the threads.
Also, actually calling a Threads interrupt() method is generally a nicer approach as then it will get out of blocking actions that throw InterruptedException (wait/sleep for example). Then it will set a flag that is already there in Threads (which can be checked with isInterrupted() or checked and cleared with interrupted(). For example the following code can replace your current code:
public class UsingFlagToShutdownThread extends Thread {
public void run() {
while (!isInterrupted()) {
System.out.print(".");
System.out.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) { interrupt(); }
}
System.out.println("Shutting down thread");
}
public static void main(String[] args)
throws InterruptedException {
UsingFlagToShutdownThread t = new UsingFlagToShutdownThread();
t.start();
Thread.sleep(5000);
t.interrupt();
}
}
i added a utlility class which essentially had a static map and methods.
the map was of type Long id, Thread thread. I added two methods one to add to the map and one to stop the thread via the use of interrupt. This method took the id as a parameter.
I also changed my loop logic from while true, too while ! isInterrupted. Is this approach ok or is this bad programming style/convention
thanks

Why volatile is not working properly

Today I was creating one timeout job using TimerTask but fell in to a new problem where i have a static volatile boolean variable flag. My understanding is as soon as value of this variable get changed it is notified by all running thread. But when I ran this program I got below output which is not acceptable.
O/P:
--------------
--------------
DD
BB
Exiting process..
CC
My expectation is my last print should be Exiting process.. Why is this strange behavior?
My code is:
public class TimeOutSort {
static volatile boolean flag = false;
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
flag = true;
System.out.println("Exiting process..");
// System.exit(0);
}
}, 10 * 200);
new Thread(new Runnable() {
#Override
public void run() {
while (!flag)
System.out.println("BB");
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (!flag)
System.out.println("CC");
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (!flag)
System.out.println("DD");
}
}).start();
}
}
Edit: How can i achieve this ?
volatile pretty much means that each time a thread accesses a variable it must ensure to use the version visible to each thread (i.e. no per-thread caching).
This doesn't force the CC-printing thread to actually get to run immediately after the flag has been set to true. It's entirely possible (especially on a single-core machine) that one thread sets the flag and prints the message before the CC-printing thread even had a chance to run.
Also: note that printing to System.out involves acquiring a lock (somewhere inside the println() call), which can modify the multi-threaded behaviour of test code.
Threads can execute code in any order
thread BB: while (!flag) // as flag is false
thread Main: flag = true;
thread Main: System.out.println("Exiting process..");
thread BB: System.out.println("BB");
My expectation is my last print should be Exiting process..
Threads are designed to run concurrently and independently. It would be surprising if this was always the last statement because you can't be sure where each thread is when you set the flag.
The thread that prints "CC" happened not to receive any CPU time until after your thread that prints "Exiting process..." printed that. This is expected behavior.
It's not volatile not working (if it were not, some of your threads would not have stopped). It's about the order of execution of instructions in the different threads, and this is random (depends on OS scheduling) unless you explicitly synchronize the loops at intermediate steps.
To add an alternative phrasing to the explanations you got: in your sample output, the thread that prints "CC" got suspended (somewhere) "between" the lines while (!flag) and System.out.println(). Which means that after it wakes up, the println() executes before the next check of the flag. (It also won't get woken up just because you change the flag value, but because some other thread blocks or uses up its time slice.)
i didn't test it , but you may achieve it like this
public class TimeOutSort {
static volatile boolean flag = false;
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
synchronized(flag){
flag = true;
notifyAll();
}
}
}, 10 * 200);
new Thread(new Runnable() {
#Override
public void run() {
synchronized(flag){
if(!flag)
{
wait();
}
System.out.println("BB");
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
synchronized(flag){
if(!flag)
{
wait();
}
System.out.println("CC");
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
synchronized(flag){
if(!flag)
{
wait();
}
System.out.println("DD");
}
}
}).start();
}
}

One thread not stopping other . Even with volatile variable

I am test a scenario to use volatile variable to stop one running thread from another.
I wonder why its not working. Where is the problem?
My code is:
public class StoppableTask extends Thread {
private volatile boolean pleaseStop;
public void run() {
System.out.println("Running..");
while (!pleaseStop) {
System.out.println("Working...");
}
}
public void tellMeToStop() {
pleaseStop = true;
}
}
public class Stopper extends Thread {
StoppableTask t ;
public Stopper(StoppableTask t){
this.t=t;
}
public void run(){
System.out.println("Ok..running too..");
try {
System.out.println("Waiting..");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.tellMeToStop();
System.out.println("Done Waiting..");
}
public class QuickTest{
public static void main(String[] args) {
StoppableTask t = new StoppableTask();
Stopper s = new Stopper(t);
t.start();
s.start();
}
}
I suspect that your program is printing so much output to the terminal that it is blocking waiting for the output to be displayed. It looks like it is not stopping but really it will. You just need to wait... for a long time...
You should put a Thread.sleep(100); inside of of the while() spin loop in StoppableTask.run() to slow down that output. Another way to do it is to remove the System.out and just increment a counter or something.
I just tried it and your program finishes in 5 seconds as expected:
public void run() {
System.out.println("Running..");
while (!pleaseStop) {
// System.out.println("Working...");
}
System.out.println("Stopped task Done");
}
Your program is correct.
When working with threads i suggest you to use log4j instead of system.out.println.Configure the log4j to send output to a file.
You can search your string-pattern in a file. Its easy to analyse.

Categories

Resources