Threads to print series in Sync - java

I am learning Java Threads these days and want to clear few basic doubts.
My aim is to have 3 threads each printing their respective jobs
Thread 1 will print series : 1 4 ...
Thread 2 will print series : 2 5 ...
Thread 3 will print series : 3 6 ...
I have wrote below code, and things are working fine but want to verify is my code correct??
Also, is mapOfPrinter.wait() is same as synchronized (mapOfPrinter)?
I mean to say, calling mapOfPrinter.wait(), makes the current thread (ie one who has acquired monitor) to release the lock and go in waiting state.
Also, if any thread has acquired a lock then another thread who encounters
synchronized (mapOfPrinter) has to wait for lock to be released. In both cases, waiting is same or it differs?
If multiple threads are waiting for lock to be freed (mapOfPrinter here), then doing mapOfPrinter.notify() will awake which thread among waiting threads.
how we can awake only particular thread among the list of threads waiting on same mutex?
Let me know if I am not clear in explaining the question.
public class Main {
public static void main(String[] args) {
Map<String, Printer> mapOfPrinter=new HashMap<String, Printer>();
Printer p1 = new Printer(1, mapOfPrinter);
Printer p2 = new Printer(2, mapOfPrinter);
Printer p3 = new Printer(3, mapOfPrinter);
Thread t1 =new Thread(p1, "1");
Thread t2 =new Thread(p2, "2");
Thread t3 =new Thread(p3, "3");
mapOfPrinter.put("1", p1);
mapOfPrinter.put("2", p2);
mapOfPrinter.put("3", p3);
t1.start();
t2.start();
t3.start();
}
}
class Printer implements Runnable{
int data;
Map<String, Printer> mapOfPrinter;
static volatile int seriesToPrint=1;
public Printer(int data, Map<String, Printer> mapOfPrinter) {
this.data=data;
this.mapOfPrinter=mapOfPrinter;
}
#Override
public void run() {
while(true){
synchronized (mapOfPrinter) {
if(seriesToPrint>mapOfPrinter.size()){
seriesToPrint=1;
}
Thread currThread = Thread.currentThread();
if(!(currThread.getName().equals(String.valueOf(seriesToPrint)))){
mapOfPrinter.notifyAll();
try {
mapOfPrinter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
Printer p = mapOfPrinter.get(String.valueOf(seriesToPrint));
System.out.println("Thread"+ currThread.getName() + " = " + p.data + " ");
p.data=p.data+3;
seriesToPrint++;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

Verifying your code is correct is a wide and difficult subject. You can get startet with testing it, and then do more testing. This will give you a confidence that your code works, but will never tell you if it is really correct. The other way to go is to do a formal verification, but this is difficult and time consuming.
xxx.wait() is totally different from synchronized(xxx) {}. Using synchronized, you make sure only a single thread at a time can enter specific regions of code. xxx.wait() makes the current thread wait until some other thread calls xxx.notify(). As you seem to have missed something fundamental here, I'd suggest digging through http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
notify() will wake up one random thread.
afaik this is not possible. You could however use a different lock for each thread, and use the respective lock.

Related

Lock by synchronize is acquired by shortest waiting threads

I know that the synchronize(LOCK) is unfair, which means there is no guarantee that the longest waiting thread will win the lock. However in my little experiment below it seems that the lock was acquired by shortest waiting threads...
public class Demo {
public static final Object LOCK = new Object();
public void unfairDemo(){
// Occupy the lock for 2 sec
new Thread(() -> {
synchronized (LOCK) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// Spawn 10 new threads, each with 100ms interval, to see which can win the lock
// If lock is fair then it should print the i in asc order
for (var i = 0; i < 10; i++) {
int finalI = i;
new Thread(() -> {
System.out.println("Added " + String.valueOf(finalI) + "th element to wait for lock");
synchronized (LOCK) {
System.out.println("I got the lock, says " + String.valueOf(finalI) + "-th thread");
}
}).start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
// Keep the program alive
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Running unfairDemo() prints the following:
Added 0th element to wait for lock
Added 1th element to wait for lock
Added 2th element to wait for lock
Added 3th element to wait for lock
Added 4th element to wait for lock
Added 5th element to wait for lock
Added 6th element to wait for lock
Added 7th element to wait for lock
Added 8th element to wait for lock
Added 9th element to wait for lock
I got the lock, says 9-th thread
I got the lock, says 8-th thread
I got the lock, says 7-th thread
I got the lock, says 6-th thread
I got the lock, says 5-th thread
I got the lock, says 4-th thread
I got the lock, says 3-th thread
I got the lock, says 2-th thread
I got the lock, says 1-th thread
I got the lock, says 0-th thread
I expected that the order would be scrambled, but no matter how I tried the results are in reverse order. What did I do wrong here?
There are many sources, such as this, that already indicate that there should be no assumption regarding the order in which threads acquire locks. But it doesn't mean the order has to be scrambled.
It probably depends at the very least on the JVM implementation. For example, this document about HotSpot says:
Contended synchronization operations use advanced adaptive spinning techniques to improve throughput even for applications with significant amounts of lock contention. As a result, synchronization performance becomes so fast that it is not a significant performance issue for the vast majority of real-world programs.
...
In the normal case when there's no contention, the synchronization operation will be completed entirely in the fast-path. If, however, we need to block or wake a thread (in monitorenter or monitorexit, respectively), the fast-path code will call into the slow-path. The slow-path implementation is in native C++ code while the fast-path is emitted by the JITs.
I'm not an expert on HotSpot (maybe someone else can provide a more authoritative answer), but based on the C++ code, it looks like the contending threads will be pushed onto a LIFO structure, which may explain the stack-like order you observed:
// * Contending threads "push" themselves onto the cxq with CAS
// and then spin/park.
...
// Cxq points to the set of Recently Arrived Threads attempting entry.
// Because we push threads onto _cxq with CAS, the RATs must take the form of
// a singly-linked LIFO.
What did I do wrong here?
You do all right.
Your expirement shows program execution order in this particular case. Java do not guarantee any order of threads execution without special efforts from programmer's side.
Try this to see chaos:
public class Demo {
public static final Object LOCK = new Object();
public void unfairDemo() {
createThread(0).start();
for (var i = 1; i < 5; i++) {
createThread(i).start();
}
}
private static Thread createThread(final int number) {
return new Thread(() -> {
System.out.println("Added " + number + "th element to wait for lock");
synchronized (LOCK) {
System.out.println("I got the lock, says " + number + "-th thread");
try {
Thread.sleep(number == 0 ? 2000 : 100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
}
public static void main(String[] args) {
new Demo().unfairDemo();
}
}

Only 2 threads for invoking produce and consume?

Below is the code concerning Thread running a producer and a consumer.
public class PC1 {
public static final int limit = 3;
public static void main(String[] args) {
List bag = new ArrayList();
Producer p = new Producer(bag);
Consumer c = new Consumer(bag);
Thread t1 = new Thread(p, "t1");
Thread t2 = new Thread(c, "t2");
Thread t3 = new Thread(p, "t3");
Thread t4 = new Thread(c, "t4");
Thread t5 = new Thread(p, "t5");
Thread t6 = new Thread(c, "t6");
t2.start();
t4.start();
t6.start();
t1.start();
t3.start();
t5.start();
}
}
class Producer implements Runnable {
private List bag;
public Producer(List bag) {
this.bag = bag;
}
#Override
public void run() {
synchronized (bag) {
while (true) {
while (bag.size() >= PC1.limit) {
bag.notify();
System.out.println(Thread.currentThread().getName() + "###########");
try {
bag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int curr = bag.size();
bag.add(++curr);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " produce " + curr);
}
}
}
}
class Consumer implements Runnable {
private List bag;
public Consumer(List bag) {
this.bag = bag;
}
#Override
public void run() {
synchronized (bag) {
while (true) {
while (bag.size() <= 0) {
bag.notify();
System.out.println(Thread.currentThread().getName() + "!!!!!!!!!!!");
try {
bag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int curr = bag.size();
bag.remove(curr - 1);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " consume " + (bag.size() + 1));
}
}
}
}
t2!!!!!!!!!!!
t3 produce 1
t3 produce 2
t3 produce 3
t3###########
t1###########
t6 consume 3
t6 consume 2
t6 consume 1
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
t6!!!!!!!!!!!
t4!!!!!!!!!!!
.
.
....like this all the time t6 and t4 alternate
above is the result on my console.As you can see:t2,t3,t1 obtain chance to excute at the beginning,then t6 and t4 alternate,other threads would never get chance to excute.
let me interpret its process.
First,t2 gets privilege to consume,bag.size=0,wait
then,t3 gets privilege to produce,after 3 times,bag is full,notify t2 to make it enter competing state,self wait
then,t1 gets privilege to product,as bag is full,notify t3 to make it enter competing state,self wait
then,t6 gets privilege to consume,after 3 times,bag is empty,notify t3 to make it enter competing state,self wait
then,t4 gets privilege to consume,as bag is empty,notify t6 to make it enter competing state,self wait
.
.
.
I m confused about before t4 wait,all other 5 thread are in competing state,however,the result shows only t4 and t6 alternate,other threads would never get chance to excute.Why that happens?
And another question is that if I modify notify to notifyAll,all 6 threads do get chance to excute.In my understanding,if multi threads are all in competing state,they all should have chance to excute.
Notify is working correctly; i.e. according to how it is specified. The "problem" is that Java does not guarantee fair scheduling for wait / notify / notifyAll. That means that some threads may get more of the work than others do.
In fact, for a normal program, this does not matter: it is not a problem at all. For example, in a normal multi-threaded producer / consumer application, it doesn't matter which consumer thread processes the things produced by the producers. All that matters is that they are processed efficiently. Indeed, there can be performance advantages in the using unfair thread scheduling instead of fair. One reason is that you can reduce the number of thread context switches.
So how would you achieve your goal?
First of all, don't use wait / notify. If you read the javadocs for these methods, you will see that there is no guarantee of fairness.
One way to get fairness would be to use a ReentrantLock instantiated with fair == true; see the javadoc for details.
If you are going to have more than just one producer and just one consumer, then you must either use notifyAll(); or you must abandon wait()/notify() altogether, switch to a ReentrantLock instead, and use two Conditions.
The problem with using notify() when there are multiple producers or consumers is that it is possible, in some situations, for a producer to wake another producer or, for a consumer to wake another consumer. Once that happens, the cycle is broken, and your program will no longer be able to make any progress. Kind of like a deadlock: Every thread is waiting for some other thread to do something.
The fancy solution to the problem is to have separate Condition variables: One for producers to wake consumers, and one for consumers to wake producers. The blunt-force way to solve the problem is to use notifyAll() and just wake everybody up.
Stephen's answer is good but fairness is not the only issue, you have so many inaccurate assumptions about how wait works that it would be tiresome to enumerate them all. The wait method is very hard to understand.
James' answer makes a very good point (+1 from me). You can't depend on any particular thread getting notified. Using separate conditions for readers and writers is a good idea to avoid notifyAll.
Big picture, the threads that access your data structure shouldn't be doing the synchronizing, the data structure should be protecting its own state (with synchronization or ReentrantLock or whatever). Reorganize to do that and the program will get a lot easier to write. Also you could read the Oracle tutorial to clear up your misunderstandings about how wait/notify works.

Program gets halted: wait() and notify()

I am trying to achieve this: Created two different threads, one prints odd numbers, one prints even numbers. Once one thread prints a number, it has to wait for the other thread and so on, that is one-after-other.
To achieve this, i am using synchronized block along with wait() and notify().
I am creating a class whose's object will be used to pass to synchronized block in both the threads.
Here is the code:
--> This is used object which will be passed to synchronized block.
package com.vipin.multithread.variousdemos;
public class SyncObject {
public SyncObject () {
}
}
Odd Thread:
package com.vipin.multithread.variousdemos;
public class OddThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int odd_nums[] = {1,3,5,7,9};
public OddThread(SyncObject so) {
t = new Thread(this,"Odd Thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while (true) {
synchronized(so) {
System.out.println("Odd num is --->" + odd_nums[index]);
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
so.notify();
if(index>=5) {
return;
}
}
}
}
}
Even Thread: UPDATE
package com.vipin.multithread.variousdemos;
public class EvenThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int even_nums[] = {2,4,6,8,10};
public EvenThread(SyncObject so) {
t = new Thread(this, "Even thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while(true) {
synchronized(so) {
System.out.println("Even num is --->" + even_nums[index]);
so.notify(); <-- Here we are notifying.
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
//so.notify(); <-- commented out.
if(index>=5) {
break;
}
}
}
}
}
Main Application:
package com.vipin.multithread.variousdemos;
public class EvenOddDemo {
public static void main(String[] args) throws InterruptedException {
SyncObject so = new SyncObject();
OddThread ot = new OddThread(so);
EvenThread et = new EvenThread(so);
System.out.println("\nIn main thread");
Thread.sleep(1000000000);
System.out.println("Exiting main thread...");
}
}
---> As seen in the code, I am creating two threads to print even and odd numbers. I am using synchronized block, and passing object of type ==> SyncObject.
SyncObject I am passing as argument to these different threads in main.
However, this programs halts, i.e stuck only first statement gets executed, and then it waits forever:
Here is the output:
Odd num is --->1
In main thread
Even num is --->2
I am not able to understand why this program waits for ever, I am using SAME object on which we are invoking synchronized(), wait() and notify(). As per my understanding, it should work, not sure why this is not working.
Any clues as to why this is waiting forever.
UPDATE:
I did some changes in the code, UPDATE and it works fine.
I still have some doubt. Does notify() be called by the thread even if it has not locked the monitor, like in my case after i updated the code.
Sequence of events:
Odd thread gets executed first, then it calls wait() <-- it releases the monitor and now in sleep mode.
Even thread runs, prints msg, and calls notify() <-- here i am not having clear understanding.
When Even thread calls notify(), at that point it has the monitor, so when it calls notify(), does is still own the monitor?
Now, after Even thread calls notify(), then Odd thread gets notified, and hence it starts execution from the point it was sleeping. It is doing some execution and calls notify(), at that points I presume Odd thread is NOT owning the monitor, it calls notify(). So, my question is, does notify() work same whether or not the thread owns the monitor?
It is only when one do the code, one really understands this. I read book and i felt i understood everything, and seems i am back to square one!
The problem here is simply that both threads go straight into wait. Thread 1 gets so, prints value then waits. Thread 2 then gets so, prints value then waits. So both are sleeping away, since nobody is there to notify them. So, a simple fix would be to do so.notify(), right before so.wait(). Then they're not infinitely waiting.
EDIT
Odd thread starts, executes & then waits. Then even thread starts, executes, notifies & then waits. Even thread holds the lock over the monitor until it goes into wait.
When the even thread called on notify, the odd thread awakens & polls for the lock. Once the even thread goes into wait (& releases the lock), then the odd thread can obtain the lock.
If the even thread had not called on notify, then the odd thread would continue to sleep. The even thread would have gone to wait & released the lock. No thread is polling or attempting to obtain the lock, hence the program remains in the suspended state.
The documentation also provides a similar explanation. I hope that clears your doubts.

Java: two WAITING + one BLOCKED threads, notify() leads to a livelock, notifyAll() doesn't, why?

I was trying to implement something similar to Java's bounded BlockingQueue interface using Java synchronization "primitives" (synchronized, wait(), notify()) when I stumbled upon some behavior I don't understand.
I create a queue capable of storing 1 element, create two threads that wait to fetch a value from the queue, start them, then try to put two values into the queue in a synchronized block in the main thread. Most of the time it works, but sometimes the two threads waiting for a value start seemingly waking up each other and not letting the main thread enter the synchronized block.
Here's my (simplified) code:
import java.util.LinkedList;
import java.util.Queue;
public class LivelockDemo {
private static final int MANY_RUNS = 10000;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < MANY_RUNS; i++) { // to increase the probability
final MyBoundedBlockingQueue ctr = new MyBoundedBlockingQueue(1);
Thread t1 = createObserver(ctr, i + ":1");
Thread t2 = createObserver(ctr, i + ":2");
t1.start();
t2.start();
System.out.println(i + ":0 ready to enter synchronized block");
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
t1.join();
t2.join();
System.out.println();
}
}
public static class MyBoundedBlockingQueue {
private Queue<Object> lst = new LinkedList<Object>();;
private int limit;
private MyBoundedBlockingQueue(int limit) {
this.limit = limit;
}
public synchronized void addWhenHasSpace(Object obj) throws InterruptedException {
boolean printed = false;
while (lst.size() >= limit) {
printed = __heartbeat(':', printed);
notify();
wait();
}
lst.offer(obj);
notify();
}
// waits until something has been set and then returns it
public synchronized Object getWhenNotEmpty() throws InterruptedException {
boolean printed = false;
while (lst.isEmpty()) {
printed = __heartbeat('.', printed); // show progress
notify();
wait();
}
Object result = lst.poll();
notify();
return result;
}
// just to show progress of waiting threads in a reasonable manner
private static boolean __heartbeat(char c, boolean printed) {
long now = System.currentTimeMillis();
if (now % 1000 == 0) {
System.out.print(c);
printed = true;
} else if (printed) {
System.out.println();
printed = false;
}
return printed;
}
}
private static Thread createObserver(final MyBoundedBlockingQueue ctr,
final String name) {
return new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println(name + ": saw " + ctr.getWhenNotEmpty());
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}, name);
}
}
Here's what I see when it "blocks":
(skipped a lot)
85:0 ready to enter synchronized block
85:0 entered synchronized block
85:2: saw hello
85:1: saw world
86:0 ready to enter synchronized block
86:0 entered synchronized block
86:2: saw hello
86:1: saw world
87:0 ready to enter synchronized block
............................................
..........................................................................
..................................................................................
(goes "forever")
However, if I change the notify() calls inside the while(...) loops of addWhenHasSpace and getWhenNotEmpty methods to notifyAll(), it "always" passes.
My question is this: why does the behavior vary between notify() and notifyAll() methods in this case, and also why is the behavior of notify() the way it is?
I would expect both methods to behave in the same way in this case (two threads WAITING, one BLOCKED), because:
it seems to me that in this case notifyAll() would only wake up the other thread, same as notify();
it looks like the choice of the method which wakes up a thread affects how the thread that is woken up (and becomes RUNNABLE I guess) and the main thread (that has been BLOCKED) later compete for the lock — not something I would expect from the javadoc as well as searching the internet on the topic.
Or maybe I'm doing something wrong altogether?
Without looking too deeply into your code, I can see that you are using a single condition variable to implement a queue with one producer and more than one consumer. That's a recipe for trouble: If there's only one condition variable, then when a consumer calls notify(), there's no way of knowing whether it will wake the producer or wake the other consumer.
There are two ways out of that trap: The simplest is to always use notifyAll().
The other way is to stop using synchronized, wait(), and notify(), and instead use the facilities in java.util.concurrent.locks.
A single ReentrantLock object can give you two (or more) condition variables. Use one exclusively for the producer to notify the consumers, and use the other exclusively for the consumers to notify the producer.
Note: The names change when you switch to using ReentrantLocks: o.wait() becomes c.await(), and o.notify() becomes c.signal().
There appears to be some kind of fairness/barging going on using intrinsic locking - probably due to some optimization. I am guessing, that the native code checks to see if the current thread has notified the monitor it is about to wait on and allows it to win.
Replace the synchronized with ReentrantLock and it should work as you expect it. The different here is how the ReentrantLock handles waiters of a lock it has notified on.
Update:
Interesting find here. What you are seeing is a race between the main thread entering
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
while the other two thread enter their respective synchronized regions. If the main thread does not get into its sync region before at least one of the two, you will experience this live-lock output you are describing.
What appears to be happening is that if both the two consumer threads hit the sync block first they will ping-pong with each other for notify and wait. It may be the case the JVM gives threads that are waiting priority to the monitor while threads are blocked.

threads reagarding notification

I was going through threads and I read that ..The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object's waiting pool.
The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object.
Now my query is that if Lets say I have 5 threads waiting and through Notify() , i want to send to notification to thread 3 only, what logic should be there that notification is sent to thread 3 only ..!!
You can't directly do this with wait and notify. You'd have to set a flag somewhere, have the code in the thread check it and go back to waiting if it's the wrong thread, and then call notifyAll.
Note that if you have to deal with this, it might be a sign that you should restructure your code. If you need to be able to notify each individual thread, you should probably make each of them wait on a different object.
wait-notify is rather a low level mechanism to indicate to other threads that an event (being expected occured). Example of this is producer/consumer mechanism.
It is not a mechanism for threads to communicate to each other.
If you need something like that you are looking in the wrong way.
The following code starts up five threads and sets the third one a flag which tells it that it is the only to continue. Then all of the threads that are waiting on the same lock object lock are notified (woken-up), but only the one selected continues. Be careful, writing multi-threaded applications is not easy at all (proper synchronization, handling the spurious wake-ups, etc.) You should not need to wake up only one particular thread from the group as this points to an incorrect problem decomposition. Anyway, here you go...
package test;
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.start(5);
}
private void start(int n) {
MyThread[] threads = new MyThread[n];
for (int i = 0; i < n; i++) {
threads[i] = new MyThread();
/* set the threads as daemon ones, so that JVM could exit while they are still running */
threads[i].setDaemon(true);
threads[i].start();
}
/* wait for the threads to start */
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
/* tell only the third thread that it is able to continue */
threads[2].setCanContinue(true);
/* wake up all threads waiting on the 'lock', but only one of them is instructed to continue */
synchronized (lock) {
lock.notifyAll();
}
/* wait some time before exiting, thread two should be able to finish correctly, the others will be discarded with the end of the JVM */
for (int i = 0; i < n; i++) {
try {
threads[i].join(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Done!");
}
/** synchronization object, i.e. a lock which makes sure that only one thread can get into "Critical Section" */
private final Object lock = new Object();
/** A simple thread to demonstrate the issue */
private final class MyThread extends Thread {
private volatile boolean canContinue;
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + " going to wait...");
synchronized (lock) {
while (!canContinue) {
try {
lock.wait(1000); /* one second */
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
System.out.println(Thread.currentThread().getName() + " woken up!");
}
public void setCanContinue(boolean canContinue) {
this.canContinue = canContinue;
}
};
}
The output of the code is:
Thread-0 going to wait...
Thread-2 going to wait...
Thread-3 going to wait...
Thread-1 going to wait...
Thread-4 going to wait...
Thread-2 woken up!
Done!
So you can clearly see that only the third thread (indexed from zero) is woken up. You have to study the Java synchronization and multi-threading in more detail to understand every particular line of the code (for example, here).
I would like to help you more, but I would have to write almost a book about Java threads and that is why I just pointed out to this Java Tutorial on threads. You are right, this problematics is not easy at all, especially for beginners. So I advise you to read through the referenced tutorial and then you should be able to understand most of the code above. There is no easy way around or at least I do not know of any.

Categories