I am trying to generate Odd/Even numbers using 2 threads using wait notify.
But It is just printing 1.
Below is the code:
Even.java
public class Even implements Runnable {
private int i; private Object ob
public Even(int i,Object o) {
this.i=i;
this.ob=o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (i % 2 == 0) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
System.out.println(i);
ob.notifyAll();
}
}
}
}
Odd.java
public class Odd implements Runnable {
private int i; private Object ob;
public Odd(int i) {
this.i=i;
this.ob=o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (i % 2 == 1) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
System.out.println(i);
ob.notifyAll();
}
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
int i = 0;
Object lock = new Object();
Thread t1 = new Thread(new Even(i),lock);
Thread t2 = new Thread(new Odd(i),lock);
t1.start();
t2.start();
}
}
Output:
1
Can anyone tell me where I am making the mistake?
Hmm, I would assume that it could be a problem that Integer appears to be immutable in Java. Thus you will not synchronize on the same objects anymore, if one of the two classes changed the i value (which it apparently does since the first output is 1).
So since you change the value stored in i in Odd and call notifyAll on the new object I that Java will complain since you call notifyAll on an object that actually never has been locked.
The threads have fallen into INDEFINITE WAITING state. Note that (t1 i.e instance of Even and t2 i.e instance of Odd), each have a separate copy of instance variable i.
Here is whats going on behind the scenes:
Initially, both thread t1 (Even) and t2 (Odd) are in READY and then RUNNABLE state
Lets assume t1 is scheduled and gets processor to execute. t1 enters RUNNING state. t1's run() is invoked
while(true) succeeds and control enters outer while loop
because of synchronized(ob) t1 locks object ob
since i is 0 initially; i % 2 == 0 condition evaluates to true
control now enters body of inner while loop, then try block and invokes ob.wait();
t1 enters WAITING state and waits until someone notifies on object ob
Now, t2 is scheduled and gets processor to execute. t2 enters RUNNING state
while(true) succeeds and control enters outer while loop
because of synchronized(ob) t2 locks object ob
i is 0 initially (remember the i incremented previously was local to t1 - Even.i). The variable i in this context is local to t2 i.e. Odd.i.
Hence i % 2 == 1 evaluates to false and control skips inner while loop
Control reaches i++; i is incremented from 0 to 1
The statement System.out.println(i); prints 1 to console
contorl moves to next line and ob.notifyAll(); is invoked and all the threads waiting on object ob (t1 in our case) are notified
At this point, both t1 and t2 are back in RUNNABLE state again
Depends on processor which thread to schedule
Lets assume t1 is scheduled and gets processor to execute
t1 resumes its operations from where it left previously (i.e the statement after ob.wait();)
control reaches catch (InterruptedException e) and since there is no exception, its skipped and control comes back to while ( i % 2 == 0) check
Remember, t1's i (i.e Even.i) is still 0 because control din't reach the line i++; in Even class
Hence i % 2 == 0 evaluates to true and control enters into body of while loop, then enters the try block and invokes ob.wait();
t1 enters WAITING state again and waits until someone notifies on object ob
Now, t2 is scheduled and gets processor to execute. t2 enters RUNNING state
t2 resumes its operations from where it left previously (i.e the statement after ob.notifyAll();)
since there is no other statement after ob.notifyAll();, the control reaches outer while loop
while(true) is evaluated and control enters body of outer while loop
because of synchronized(ob) t1 locks object ob
Remember t2's i is now 1 because it was incremented previously and printed on console
Hence, while ( i % 2 == 1) is evaluated to true and control enters body of inner while loop, then try block and invokes ob.wait();
As a result, t2 enters WAITING state
t1 and t2 are both in WAITING state now; waiting on object ob. Waiting for someone to notify them on object ob. Sadly, there is no one to rescue
Hence the INDEFINITE WAITING
Following code should help in what you are trying to achieve
public class EvenOddTest {
public static void main(String[] args) {
Lock lock = new Lock();
Thread t1 = new Thread(new Even(lock));
Thread t2 = new Thread(new Odd(lock));
t1.start();
t2.start();
}
}
class Lock {
private int data;
public void increment() {
data++;
}
public int getData() {
return data;
}
}
class Even implements Runnable {
private Lock ob;
public Even(Lock o) {
this.ob = o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (ob.getData() % 2 == 0) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ob.increment();
System.out.println(ob.getData());
ob.notifyAll();
}
}
}
}
class Odd implements Runnable {
private Lock ob;
public Odd(Lock o) {
this.ob = o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (ob.getData() % 2 == 1) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ob.increment();
System.out.println(ob.getData());
ob.notifyAll();
}
}
}
}
Note:
I have refactored your code so that the object on which threads try to obtain lock and wait upon, holds the data as well.
lock object is now the shared instance between Even and Odd threads.
With my previous reasoning, the code should be self explanatory.
This is not actual way of doing things in parallel computing, to leverage multi-threading power/capabilities. However, it should be a good starter exercise.
You can put i variable as a class attribute in Test class, then create an object of type Test and pass it as parameter to the constructors:
public class Test {
public Integer i = 0;
public static void main(String[] args) {
Object o = new Object();
Test t = new Test();
Thread t1 = new Thread(new Even(t,o));
Thread t2 = new Thread(new Odd(t,o));
t1.start();
t2.start();
}
}
public class Even implements Runnable {
private Test t;
private Object o;
public Even(Test t, Object o) {
this.t=t;
this.o=o;
}
#Override
public void run() {
while (true) {
synchronized (o) {
while (t.i % 2 == 0) {
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t.i++;
System.out.println(t.i);
o.notifyAll();
}
}
}
}
public class Odd implements Runnable {
private Test t;
private Object o;
public Odd(Test t, Object o) {
this.t=t;
this.o = o;
}
#Override
public void run() {
while (true) {
synchronized (o) {
while (t.i % 2 == 1) {
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t.i++;
System.out.println(t.i);
o.notifyAll();
}
}
}
}
Related
Can this code deadlock with thread 1 calling one and thread 2 calling two. That is, can the acquisition of the inner lock be reordered to before the acquisition of the outer one (from the POV of the other thread)?
private final Object foo = new Object();
synchronized void one() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
synchronized void two() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
No, this will not deadlock.
When synchronized methods are called the intrinsic lock of this is locked before the method’s body is executed. Here either thread 1 or thread 2 will get to run its method, and the other one will not be able to lock on the intrinsic lock of this.foo so the owner of the lock of this will be able to lock this.foo.
So for with a Simple Test :
class LockTest implements Runnable {
public final Object foo = new Object();
boolean runOne;
public LockTest(boolean runOne) {
this.runOne = runOne;
}
synchronized void one() {
System.out.println("runnin one function");
synchronized(this.foo) {
try {
System.out.println("Enter Sleep function one");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void two() {
System.out.println("running two function");
synchronized(this.foo) {
try {
System.out.println("enter sleep function two");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void run() {
if(runOne)
one();
else
two();
}
}
With this in a Main class :
while (true)
{
LockTest document2 = new LockTest(true);
LockTest document3 = new LockTest(false);
Thread tread1 = new Thread(document2);
Thread tread2 = new Thread(document3);
tread1.start();
tread2.start();
a++;
if(a==10)
break;
}
We are not locking and even watching with a Thread Dump everything is working Fine. Why? Because every time we are initializating a new Thread with a new object foo. But if that object is declared as static it will be a lock and the others threads need to wait. So from my test and POV. No, it can't be deadlocked.
I am reading some code in OCA/OCP Java SE 7 Programmer I & II Study Guide, and I got stuck on an example:
package threads;
class Totalizer implements Runnable
{
int total = 0;
public void run(){
synchronized(this){
for(int i = 0; i < 100; i++){
total += i;
}
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t){
try {
System.out.println("Waiting for calculation...");
t.wait();
} catch (InterruptedException e) {}
System.out.println(t.total);
}
}
public static void main(String[] args){
Totalizer t = new Totalizer();
new Tester(t).start();
new Tester(t).start();
new Tester(t).start();
}
}
//
When I run main(), it prints:
waiting for calculation...
waiting for calculation...
waiting for calculation...
and nothing happens, no calculation, nothing. I can't figure out what is wrong with this code.
Two points.
The most obvious one is that you never start the Totalizer runnable, so the notifyAll call is never issued. You need to have a line
new Thread(t).start();
somewhere in your main method. But even if you do that, it won't work reliably, as the wait call may be invoked after the notifyAll call. It may also print the output too early, as the wait call can wake up without a notifyAll as well.
The Javadoc for Object.wait() describes what you need to do:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
So, you can't just call Object.wait just like that, if you want to use it correctly. This is because:
You don't know if the condition was already satisfied earlier, before you started waiting
The wait call may also wake up without a notify call
In your case, you need a condition variable that you can check. For example, you can change your code like this:
class Totalizer implements Runnable
{
int total = 0;
boolean calculationComplete; // Condition to check in wait()
public void run() {
for(int i = 0; i < 100; i++) {
total += i;
}
synchronized (this) {
// Indicate condition for wait() is now true
calculationComplete = true;
notifyAll();
}
}
}
class Tester extends Thread
{
Totalizer t;
public Tester(Totalizer tot){t = tot;}
public void run(){
synchronized(t) {
System.out.println("Waiting for calculation...");
// Loop, terminate when condition is true
while (!t.calculationComplete) {
try {
t.wait();
} catch (InterruptedException e) {}
}
System.out.println(t.total);
}
}
This question already has answers here:
IllegalMonitorStateException on wait() call
(12 answers)
Closed 5 years ago.
I am trying to learn Multi threading and for practice, I am trying to print odd & even number using two thread. I have created an object which will act as a lock for the both the threads. When I try to execute it throws java.lang.IllegalMonitorStateException.
class EVENODDimpl implements Runnable {
int num;
int temp = 0;
Object lock = new Object();
public EVENODDimpl( int num) {
this.num = num;
}
public void run() {
try {
synchronized (lock) {
while(temp<num) {
temp++;
System.out.println(Thread.currentThread().getName()+" "+temp);
this.notify();
this.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main Method:
public class EVENODD {
public static void main(String[] args) {
int i = 10;
EVENODDimpl ei = new EVENODDimpl(i);
Thread t1 = new Thread( ei,"EvenThread");
Thread t2 = new Thread( ei,"OddThread");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You wait and notify on this, but you should wait and notify on lock because you synchronize on lock, you can't wait and notify on other object than the one on which you're synchronizing, working version:
class EVENODDimpl implements Runnable {
int num;
int temp = 0;
Object lock = new Object();
public EVENODDimpl( int num) {
this.num = num;
}
public void run() {
try {
synchronized (lock) {
while(temp<num) {
temp++;
System.out.println(Thread.currentThread().getName()+" "+temp);
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
As it said from the javadoc
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
This means that your methods notify and wait should own monitor. Or in other words the object that is calling these method must be synchronized. Your this object is not synchronized. That's why you get this exception. Call this method from lock object in your case.
Your logic is still wrong but it is up to you to explore that.
java.lang.IllegalMonitorStateException Exception occur because you are using notify method on the object this.notify() but that Object is not synchronized.
Replace synchronized (lock) with this: synchronized (this)
Basically, I am trying to implement a mechanism where I have two threads going in parallel. Thread1 is continuously updating a counter value. When the counter value reaches increments of specific values (ex. multiple of 100, 250, 500), then I want Thread2 to execute a specific task selected on the counter value in parallel. Thread1 should continue counting but it should not count past the key value if Thread2 has not completed its' task.
Use case: Thread 1 has updated the counter to be 100. This dispatches Thread2 to perform TaskA. Thread1 is counting still. The counter reaches 250. If Thread2 has finished its' task, Thread1 should continue. Otherwise, Thread1 should wait for TaskA to be finished before proceeding.
|t2 |t1
| |
| |
| |
______100________ <----start thread 2 real quick
| |
| |
| |
| |
| |
| |
_______250______ <------at this point just wait for taskA to finish
| | IF it's not finished. If it is, start taskB and
| | continue counting
V V
I've been hacking at the problem for a bit but I've scrapped everything so far. I'd appreciate code/pseudocode/hints/advice. Thanks in advance
The CyclicBarrier can be used to create a barrier where the threads would wait for the other thread. So, below, there are two threads 'countingThread' and 'taskThread'. The 'countingThread' would perform its counting and would invoke the 'await' when the counting has reached a specific point, (method-'checkBarrierCondition' below).
As per the example in the question, when the counting-thread reaches 100, it can call 'await' on the barrier and if the task-thread has completed its task by that time, the barrier would snap and both would proceed to next activities. If the task has not been completed yet, then the counter thread will wait for the task-performing thread.
All the locking is handled by CyclicBarrier and concurrent framework
public class Threading {
public void execute() {
final CyclicBarrier barrier = new CyclicBarrier(2);
Thread countingThread = new Thread(new Tasker(barrier));
Thread taskThread = new Thread(new Counter(barrier));
countingThread.start();
taskThread.start();
try {
countingThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Threading().execute();
}
class Tasker implements Runnable {
private CyclicBarrier barrier;
Tasker(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
String task = "taskA"; //just some mock-up task name
while (!allTasksDone(task)) {
task = performTask(task);
try {
System.out.println("Tasker : Await on barrier ");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
class Counter implements Runnable {
private CyclicBarrier barrier;
Counter(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
int counter = 0; //just for the sake of example; starting at 0
while (!isCountingDone(counter)) {
counter = performCounting(counter);
if (checkBarrierCondition(counter)) {
try {
System.out.println("Counter : Await on barrier ");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
}
}
you probably want to use locks? consider this - counter:
import java.util.concurrent.locks.Lock;
public class ThreadOne extends Thread {
private ThreadTwo two;
private Lock lock;
public ThreadOne(Lock l, ThreadTwo two) {
this.two = two;
this.lock = l;
this.start();
}
#Override
public void run() {
int i = 0;
while(true) {
if(i%100==0) {
// tell other thread to start
two.startRunning();
while(two.pending()) {
// wait until it actually started
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// acquire the lock (or wait)
lock.lock();
try {
// count up
i++;
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
execution thread:
import java.util.concurrent.locks.Lock;
public class ThreadTwo extends Thread {
private boolean pending = false;
private Lock lock;
public ThreadTwo(Lock l) {
this.lock = l;
this.start();
}
public void startRunning() {
pending = true;
}
public boolean pending() {
return pending;
}
#Override
public void run() {
while(true) {
try {
Thread.sleep(200);
} catch (Exception e) {
}
if(pending) {
lock.lock();
try {
pending = false;
execute();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
}
private void execute() {
}
}
and how to start them.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) {
Lock l = new ReentrantLock();
ThreadTwo two = new ThreadTwo(l);
ThreadOne one = new ThreadOne(l,two);
}
}
package testRandomStuff;
public class ThreadingPuzzle {
public int countMax = 25;
public int factor = 5;
public Thread threadA, threadB;
private class Signal {
public volatile boolean flag = true;
public Signal(boolean initial) {
flag = initial;
}
public synchronized void setFlag() {
flag = true;
notifyAll();
}
public synchronized void unsetFlag() {
flag = false;
notifyAll();
}
public synchronized boolean getFlag() {
return flag;
}
}
public Signal checkpoint = new Signal(true);
public Signal doWork = new Signal(false);
Runnable threadARunnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i < countMax; i++) {
if (i % factor == 0) {
if (checkpoint != null) {
// --------mechanism to wait for threadB to finish---------
synchronized (checkpoint) {
try {
// -----use while loop to prevent spurious wakeup------
// Checkpoint flag is true in the first iteration, no need to wait.
while (!checkpoint.getFlag()) {
checkpoint.wait();
}
} catch (InterruptedException ie) {
// handle exception
}
}
// ThreadB has finished last job when threadA leaves the above sync-block
}
// ------ start threadB real quick---------
// unset checkpoint flag, so that threadA will not proceed the next
// interation without threadB setting the flag first.
// send signal to threadB to wake it up
checkpoint.unsetFlag();
doWork.setFlag();
}
System.out.println("Thread A - count:"+i);
}
}
};
Runnable threadBRunnable = new Runnable() {
#Override
public void run() {
while (true) {
// --------mechanism to wait for threadA send job---------
synchronized (doWork) {
try {
// -----use while loop to prevent spurious wakeup------
// doWork flag is false in the first iteration, wait for ThreadA.
while (!doWork.getFlag()) {
doWork.wait();
}
} catch (InterruptedException ie) {
// handle exception
}
}
doWork.unsetFlag();
// -----------do what ever you need to do in threadB-----------
System.out.println("Thread B - do some work");
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
System.out.println("Thread B - done working");
// ------------Finish work, notify threadA---------
checkpoint.setFlag();
}
}
};
public ThreadingPuzzle() {
// FIXME Auto-generated constructor stub
}
public static void main(String[] args){
ThreadingPuzzle puzzle = new ThreadingPuzzle();
puzzle.threadA = new Thread(puzzle.threadARunnable);
puzzle.threadB = new Thread(puzzle.threadBRunnable);
puzzle.threadA.start();
puzzle.threadB.start();
}
}
SIMULATION RESULTS
Thread B - do some work
Thread A - count:0
Thread A - count:1
Thread A - count:2
Thread A - count:3
Thread A - count:4
Thread B - done working
Thread B - do some work
Thread A - count:5
Thread A - count:6
Thread A - count:7
Thread A - count:8
Thread A - count:9
Thread B - done working
Thread B - do some work
Thread A - count:10
Thread A - count:11
Thread A - count:12
Thread A - count:13
Thread A - count:14
Thread B - done working
Thread B - do some work
Thread A - count:15
Thread A - count:16
Thread A - count:17
Thread A - count:18
Thread A - count:19
Thread B - done working
Thread B - do some work
Thread A - count:20
Thread A - count:21
Thread A - count:22
Thread A - count:23
Thread A - count:24
Thread B - done working
Thread B - do some work
Thread B - done working
I would suggest have a look at Java's executor service. It really abstracts most of the complexities associated with multiple threads. Plus you can easily increase number of threads executing tasks if required in future. Basically you run counting in your first thread. When you want to execute a task in another thread you simply create a callable. The API will return you a future(s) for your callable(s). When you have finished processing/counting in thread1 you simply call get or getValue on your future from thread1. Now the beauty of this is that it will return you the result immediately if other thread has finished processing. If other thread is busy processing the task then it will block your thread1 until result is returned. Please note that you don't need to do any locking, blocking or notifying manually. Don't forget to use threadsafe collections if you are sharing data between multiple threads. Hope this helps!
Can anybody please provide me a good small example demonstrate wait() and notify() functionality in java. I've tried with the below piece of code but it's not showing what i expected.
public class WaitDemo {
int i = 10;
int display() {
System.out.println("Lexmark");
i++;
return i;
}
}
public class ClassDemo1 extends Thread {
private WaitDemo wd = new WaitDemo();
public static void main(String[] args) {
ClassDemo1 cd1 = new ClassDemo1();
ClassDemo1 cd2 = new ClassDemo1();
cd1.setName("Europe");
cd2.setName("America");
cd1.start();
cd2.start();
}
synchronized void display() {
System.out.println("Hello");
notifyAll();
}
public void run() {
synchronized (this) {
try {
{
notify();
System.out.println("The thread is " + currentThread().getName());
wait();
System.out.println("The value is " + wd.display());
}
} catch (InterruptedException e) {
}
}
}
}
The issue is that the method in the class WaitDemo is not getting executed and as per my idea the SOP after wait() should execute. Please help me out on this.
You've got two levels of braces { in your try block. If you remove the inner set (which doesn't appear to do anything), does that fix the problem?
There are several examples around, all of which demonstrate the use. The last link is a set of results that can help you out. If you need more specific things, let me know what it is that your app is trying to do, and I can try to find examples that are more specific to your situation.
http://www.javamex.com/tutorials/wait_notify_how_to.shtml
http://www.java-samples.com/showtutorial.php?tutorialid=306
http://www.coderanch.com/t/234235/threads/java/Wait-Example
https://www.google.com/search?q=wait%28%29+example+java&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a
Below is an example of wait & notify in the Object class. The customer is trying to withdraw money of value 2000 but the account is having only 1000 so it has to wait for the deposit. Once the deposit is made, then the customer will be able to withdraw the amount. Until the deposit is made, the customer will be waiting.
class Cust {
private int totalAmount = 1000;
public synchronized void withdrawal(int amount) {
System.out.println("Total amount " + totalAmount + " withdrawing amount " + amount);
while (this.totalAmount < amount) {
System.out.println("not enough amount..waiting for deposit..");
try { wait(); } catch (Exception e) {}
}
this.totalAmount -= amount;
System.out.println("Withdrawal successful.. Remaining balance is "+totalAmount);
}
public synchronized void deposit(int amount){
System.out.println("Depositing amount "+amount);
this.totalAmount += amount;
System.out.println("deposit completed...and Now totalAmount is " + this.totalAmount);
notify();
}
}
class Depo implements Runnable {
Cust c; int depo;
Depo(Cust c, int depo){
this.c = c;
this.depo = depo;
}
#Override
public void run() {
c.deposit(depo);
}
}
class Withdrawal implements Runnable {
Cust c; int with;
Withdrawal(Cust c, int with){
this.c = c;
this.with = with;
}
#Override
public void run() {
c.withdrawal(with);
}
}
public class ObjectWaitExample {
public static void main(String[] args) {
Cust c = new Cust();
Thread w = new Thread(new Withdrawal(c, 2000));
Thread d1 = new Thread(new Depo(c, 50));
Thread d2 = new Thread(new Depo(c, 150));
Thread d3 = new Thread(new Depo(c, 900));
w.start();
d1.start();
d2.start();
d3.start();
}
}
I created two threads one for printing odd numbers (OddThread) and another for even numbers (EvenThread). Inside the run method of each of the threads I used the shared object of class Print to call printOdd() and printEven() for the Odd and EvenThread respectively. I made the shared object of Print static so that only one copy is made. Now synchronizing on the Print object I used a Boolean flag such that when the odd thread printed an odd number it will be sent into the waiting state and the at the same time notifying the even thread to execute. The logic is written in such a way that the odd thread will always print the odd number first no matter what, as the flag is set to false initially preventing the even thread to execute and sending it to a waiting state.
package com.amardeep.test;
public class ThreadDemo {
// Shared object
static Print print = new Print();
public static void main(String[] args) {
new Thread(new OddThread()).start();
new Thread(new EvenThread()).start();
}
}
class EvenThread implements Runnable {
#Override
public void run() {
ThreadDemo.print.printEven();
}
}
class OddThread implements Runnable {
#Override
public void run() {
ThreadDemo.print.printOdd();
}
}
class Print {
public volatile boolean flag = false;
public synchronized void printEven() {
for (int i = 1; i <= 10; i++) {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
if (i % 2 == 0) {
System.out.println("from even " + i);
flag = false;
notifyAll();
}
}
}
}
public synchronized void printOdd() {
for (int i = 1; i <= 10; i++) {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
if (i % 2 != 0) {
System.out.println("from odd " + i);
flag = true;
notifyAll();
}
}
}
}
}
output:-
from odd 1
from even 2
from odd 3
from even 4
from odd 5
from even 6
from odd 7
from even 8
from odd 9
from even 10
Your problem is that you are creating two instances of the Thread class. Thus when the wait() is called, it is on two different instances, neither of which has another thread that is in contention for your monitor, nor is there another thread to call notifyAll() to wake the thread from its wait state.
Thus each thread you have started will wait forever (or until interrupted for some other reason).
You want to have multiple threads accessing the same monitor, so start by trying to code something in which the code in question is not actually a thread, but is simply being used by a thread.
#normalocity has already provided links to multiple examples.
I just updated this answer to include an SCCE.
The workers call pauseIfNeeded on the WorkerPauseManager. If the manager is paused when the worker thread calls pauseIfNeeded(), we call wait(), which tells the calling thread to wait until a different thread calls notify() or notifyAll() on the object being waited on. This happens when the Swing Event Dispatch Thread calls play() on the manager, which in turn calls notifyAll().
Note that you must have a synchronized lock on the object you are calling wait() or notify() on. Since the methods in WorkerPauseManager are synchronized, all the synchronized methods are getting a synchronized lock on the WorkerPauseManager itself.
import javax.swing.*;
import java.awt.event.ActionEvent;
/**
* #author sbarnum
*/
public class WorkerPauseManagerTest {
public static void main(String[] args) {
final WorkerPauseManager pauseManager = new WorkerPauseManager();
new Worker("Worker 1", pauseManager).start();
new Worker("Worker 2", pauseManager).start();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JToggleButton playPauseButton = new JToggleButton(new AbstractAction("Pause") {
public void actionPerformed(final ActionEvent e) {
JToggleButton source = (JToggleButton) e.getSource();
if (source.isSelected()) {
pauseManager.start();
source.setText("Pause");
} else {
pauseManager.pause();
source.setText("Play");
}
}
});
playPauseButton.setSelected(true); // already running
JOptionPane.showMessageDialog(null, playPauseButton, "WorkerPauseManager Demo", JOptionPane.PLAIN_MESSAGE);
System.exit(0);
}
});
}
private static class Worker extends Thread {
final String name;
final WorkerPauseManager pauseManager;
public Worker(final String name, final WorkerPauseManager pauseManager) {
this.name = name;
this.pauseManager = pauseManager;
}
#Override
public void run() {
while (!Thread.interrupted()) {
try {
pauseManager.pauseIfNeeded();
System.out.println(name + " is running");
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public static final class WorkerPauseManager {
private boolean paused;
public synchronized void pauseIfNeeded() throws InterruptedException {
if (paused) wait();
}
public synchronized void pause() {
this.paused = true;
}
public synchronized void start() {
this.paused = false;
notifyAll();
}
}
}
What wait method does is , when some thread executed a synchronized block by locking some object (we call that object is "a") , then inside that synchronized block when the thread executed the wait method of object "a" like this
A a = new A (); // some class object call "a"
synchronized (a){
a.wait ();//exceptions must be handled
}
Then the a object will release and the thread has to go to the wait state until it has been release from that state.
and anothet thread now can use the a object beacause its a release object. so if another thread locked that object and it executed the notify method from that object like
a.notify ()
Then one of a thread of the threads that went to wait state by object "a" can be released from the wait state. Other wise when call the notifyAll then the all the thread objects will release from that state.
/*
* the below program is like
* tread t1 will first run , and it comes to "notify()" method
* there are no threds waiting bcoz this is the first thread.
* so it will not invoke any other threads. next step is "wait()" method
*will be called and the thread t1 in waiting state. next stament
* "System.out.println("The value is ..."+wd.display());" will not be executed
* because thread t1 is in waiting state.
*
* thread t2 will run ,and it comes to "notify()" method ,there is already
* thread t1 is in waiting state ,then it will be invoked.now thread t1 will
* continue execution and it prints the statement "System.out.println("The value is ..."+wd.display())"
* and thread t2 will be in waiting state now.
*
* if you uncomment "notifyAll()" method then, after t1 thread completes its execution
*then immediately "notifyAll()" method will be called,by that time thread t2 is
* already in waiting state , then thread t2 will be invoked and continues execution.
*or
* if any other threadds are in waiting state all those threads will be invoked.
*/
package threadsex;
/**
*
* #author MaheshM
*/
/**
* #param args the command line arguments
*/
public class WaitNotifyNotifyAllDemo implements Runnable {
WaitDemo wd = new WaitDemo();
public static void main(String[] args) {
WaitNotifyNotifyAllDemo cd1 = new WaitNotifyNotifyAllDemo();
Thread t1 = new Thread(cd1);
t1.setName("mahi1");
Thread t2 = new Thread(cd1);
t2.setName("mahi2");
t1.start();
t2.start();
}
#Override
public void run() {
synchronized (this) {
try {
System.out.println("The thread is=" +
Thread.currentThread().getName());
notify();
wait();
System.out.println("The value is ..." + wd.display());
// notifyAll();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}