I have two very similar programs each trying to run two threads OddThread and EvenThread and trying to print the odd and even numbers in sequence . While the first one works , the second one hangs . Can anyone please pinpoint the bug in the second program ?
The first one which works :
public class ThreadTest {
public static void main(String[] args) {
System.out.println("Odd Even test");
NumHolder objNumHolder = new NumHolder();
Odd o1 = new Odd(objNumHolder, "Odd Number Thread");
Even e1 = new Even(objNumHolder, "Even Number Thread");
o1.start();
e1.start();
}
}
class NumHolder {
private int intCurrNum;
private boolean isEven = false;
public synchronized void printOddNumber(String tname) {
while (isEven == true){
try {
wait();
}catch (InterruptedException e) {
}
}
isEven = true;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
public synchronized void printEvenNumber(String tname) {
while (isEven == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
isEven = false;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
class Even extends Thread {
private NumHolder objNumHolder;
public Even(NumHolder p_objNumHolder, String name) {
super(name);
objNumHolder=p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printEvenNumber(getName());
}
}
}
class Odd extends Thread {
private NumHolder objNumHolder;
public Odd(NumHolder p_objNumHolder,String name) {
super(name);
objNumHolder = p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printOddNumber(getName());
}
}
}
The second code which hangs :
class PrintClass {
int intCurrNum;
private boolean isEven = false;
synchronized void printOdd(){
while(isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printOdd()");
ie.printStackTrace();
}
isEven = true;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
synchronized void printEven(){
while(!isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printEven()");
ie.printStackTrace();
}
isEven = false;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
}
class ThreadOdd extends Thread {
PrintClass pc = null;
ThreadOdd(PrintClass pc , String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printOdd();
}
}
}
class ThreadEven extends Thread {
PrintClass pc = null;
ThreadEven(PrintClass pc,String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printEven();
}
}
}
public class EvenOddPrintClass {
public static void main(String[] args){
PrintClass pc = new PrintClass();
Thread to = new ThreadOdd(pc,"ThreadOdd");
Thread te = new ThreadEven(pc,"ThreadEven");
to.start();
te.start();
}
}
Thanks.
I suggest you run your code in the debugger and step through both threads. It's very educational. You will see exactly where the error is.
In both versions, isEven starts out as false.
In the first version, printOddNumber will skip the whole while loop, print the odd number, set isEven to true and notify the even thread, which will print the even number and notify the odd thread again etc. in sequence.
In the second version, printOddNumber will skip the whole while loop, including printing the number and notifying the even thread. After 10 attempts it will exit without having printed anything, and leaving the even thread hanging without ever having notified it.
Interesting. So initially the isEven = false. If the printOdd() is called first then the while (isEven) test is false so printOdd() will exit immediately without generating any output. The while loops in your first program only encompass the wait test, not the entire method.
Then when printEven() is called by the other thread, it will call wait() and hang since there is no other thread to call notifyAll().
You only should want the while loop around the wait since you are going to exit after you print out the even or odd number anyway, right? So the logic in the first program is correct.
public class CountDownApp
{
public static void main(String[] args)
{
Thread count1 = new CountDownEven();
Thread count2 = new CountDownOdd();
count1.start();
count2.start();
}
}
class CountDownEven extends Thread
{
public void run()
{
for(int i=10;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class CountDownOdd extends Thread
{
public void run()
{
for(int i=9;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Related
Here's my code:
public class ProducerConsumer
{
public static void main(String[] args)
{
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt= new ProducerT(p); // with p obj i am creating thread
ConsumerT ct=new ConsumerT(p); // with same p obj i am creating thread
pt.start();
ct.start(); //i am starting 2 threads
}
}
class ProduceCosumeData
{
boolean flag;
public synchronized void printStringP(int n)
{
for(int i=0;i<n;i++)
{
try{
if(flag) //for frist time flag is flase so, wait will skip
wait();
else
flag=true; //for next time onwards wait() will get call
System.out.print("Pay");
notify();//after this why my wait() not canceling in inprintStringC()
}catch(Exception e)
{
System.out.print(e);
}
}
}
public synchronized void printStringC(int n)
{
for(int i=0;i<n;i++)
{
try{
wait(); // why it is not out of this after notify()
System.out.print("Tm");
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
}
class ProducerT extends Thread
{
ProduceCosumeData p;
ProducerT(ProduceCosumeData p)
{
this.p=p; // i am saving the same obj for both threads
}
public void run()
{
p.printStringP(10); //it will print 10 times pay
}
}
class ConsumerT extends Thread
{
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p)
{
this.p=p; // i am saving the same obj for both threads
}
public void run()
{
p.printStringC(10); //it will print 10 times tm
}
}
I am expecting the following output:
PayTm
PayTm
PayTm
... 10 times
but what I'm getting output is this:
Pay..
This is followed by a long wait.
The above two functions are in same object.
Why is the notify not releasing the wait() function? Even when I use notifyAll(), the output remains the same.
In you code, one of your threads is calling notify and the other is still not waiting. This produces a deadlock with both threads waiting.
You need to fix your use of the synchronization flag, don't call wait if it is not needed. Also, checking the locking condition is still available after the wait() is a good practice.
This is your ProduceConsumeData class with the use of the flag fixed:
class ProduceCosumeData
{
boolean flag;
public synchronized void printStringP(int n)
{
for(int i=0;i<n;i++)
{
try{
while (flag == true) {
wait();
}
flag=true;
System.out.print("Pay");
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
public synchronized void printStringC(int n)
{
for(int i=0;i<n;i++)
{
try{
while(flag == false) {
wait();
}
System.out.print("Tm");
flag = false;
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
}
You have used a general wait() with the synchronization in the method. Try using an object-synchronised version, such as synchronized(this){ wait(); } then whatever, to prevent cyclic dependencies of multiple threads on the same object, which is very very dangerous for any multithreaded program.
Or, more simply, implement a proper clone() method in your ProducerConsumerData class, and then to the 1st thread pass this object, and to the next pass its clone. Try using p.clone() instead of p in the second thread's constructor.
As answered above, you can make printStringP() 's notify() only get called when flag is true, not always.
This is the classic misconception that trips up almost everyone who tries to use wait and notify. Really they are so old and broken they shouldn't even be taught any more IMHO.
When printStringP calls notify() printStringC is not waiting yet.
class ProduceCosumeData {
// Variable shared between threads should be volatile.
volatile boolean flag;
public synchronized void printStringP(int n) {
for (int i = 0; i < n; i++) {
try {
//for frist time flag is flase so, wait will skip
if (flag) {
System.err.println("Waiting in printStringP");
wait();
} else {
System.err.println("flag now true");
flag = true; //for next time onwards wait() will get call
}
System.out.print("Pay");
System.err.println("printStringP notify");
notify();//after this why my wait() not canceling in inprintStringC()
} catch (Exception e) {
System.out.print(e);
}
}
}
public synchronized void printStringC(int n) {
for (int i = 0; i < n; i++) {
try {
System.err.println("Waiting in printStringC");
wait(); // why it is not out of this after notify()
System.out.print("Tm");
System.err.println("printStringC notify");
notify();
} catch (Exception e) {
System.out.print(e);
}
}
}
}
class ProducerT extends Thread {
ProduceCosumeData p;
ProducerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringP(10); //it will print 10 times pay
}
}
class ConsumerT extends Thread {
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringC(10); //it will print 10 times tm
}
}
public void test() {
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt = new ProducerT(p); // with p obj i am creating thread
ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
pt.start();
ct.start(); //i am starting 2 threads
}
prints
flag now true
PayprintStringP notify
Waiting in printStringP
Waiting in printStringC
To fix this don't use wait/notify it is broken for all but the very experienced. The same functionality can be achieved in a stable fashion using Locks and Conditions or almost any other java.util.concurrent class.
In the second iteration of printStringP the attribute flag is true and then the two threads are waiting.
Please find the below code snippet.
package com.java.examples;
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt = new ProducerT(p); // with p obj i am creating thread
ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
pt.start();
Thread.sleep(1000);
ct.start(); // i am starting 2 threads
}
}
class ProduceCosumeData {
boolean flag = false;
public synchronized void printStringP(int n) {
for (int i = 0; i < n; i++) {
try {
if (flag) {
notify();
} else
flag = true;
System.out.println("Pay");
if (i <= n - 1) {
wait();
} else {
break;
}
} catch (Exception e) {
System.out.print(e);
}
}
notify();
}
public synchronized void printStringC(int n) {
for (int i = 0; i < n; i++) {
try {
if (flag) {
System.out.println("Tm");
if (i <= n - 1) {
notify();
} else {
break;
}
} else
flag = false;
wait();
} catch (Exception e) {
System.out.print(e);
}
}
}
}
class ProducerT extends Thread {
ProduceCosumeData p;
ProducerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringP(10); // it will print 10 times pay
}
}
class ConsumerT extends Thread {
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringC(10); // it will print 10 times tm
}
}
I am trying to do it using two threads like below. Can someone point the obvious mistake I am doing here?
public class OddEven {
public static boolean available = false;
public static Queue<Integer> queue = new LinkedList<Integer>();
static Thread threadEven = new Thread() {
#Override
public void run() {
printEven();
}
public synchronized void printEven() {
while (!available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = false;
notifyAll();
}
};
static Thread threadOdd = new Thread() {
#Override
public void run() {
printOdd();
}
public synchronized void printOdd () {
while (available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = true;
notifyAll();
}
};
public static void main(String[] args) {
int n = 20;
for (int i = 1; i < n; i++) {
queue.add(i);
}
threadOdd.start();
threadEven.start();
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
threadOdd.join();
threadEven.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
But this program is only printing 1 and quitting. After printing 1 the available should be true and printEven should wake up, print and set available to false. I don't understand what is going wrong here? I saw other solutions but want to know why my solution is not working.
Putting synchronized on an instance method means that the thread calling that method has to acquire the lock on that instance; public void synchronized printOdd() is syntax sugar for
public void printOdd() {
synchronized(this) {
...
}
}
where this is different for each instance, since ThreadOdd and threadEven are two different objects and each one uses its own lock. The methods notifyAll and wait are called on the object that is being used as the lock. When one thread waits it never gets notified because the notification only applies to other threads waiting on the same lock as the notifying thread.
I have created two runnable jobs: PrintEvenNumbersJob and PrintOddNumbersJob and spawned two threads to execute these jobs. This seems to work perfectly fine! But I smell something suspicious about this implementation. Can I have some comments and advice on this implementation?
The problem that I see with this implementation is that the program terminates only when thread1 gains the lock to the object lock first otherwise it print the odd first even second order and doesn't terminate unless I supply yet another statement "lock.notify" after for statement in PrintEvenNumbersJob (as in this implementation). My question here is how to make sure that thread1 is executed first.
public class PrintEvenNumbersJob implements Runnable {
private Object lock;
public PrintEvenNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i <= 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify(); // not required if thread1 gains lock first
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Object lock;
public PrintOddNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 1; i < 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();
}
}
}
public class EvenOddManager {
public static void main(String[] args) {
Object lock = new Object();
PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);
Thread thread1 = new Thread(printEvenNumbersJob);
Thread thread2 = new Thread(printOddNumbersJob);
thread2.start();
thread1.start();
}
}
Have you try using Semaphores? It's easier because you don't need to worry about the order that wait and notify are called (if you call notify before the wait, it's "lost")
Sample code:
import java.util.concurrent.*;
public class Test {
private final Semaphore oddJobPermits = new Semaphore(0);
private final Semaphore evenJobPermits = new Semaphore(1);
private class EvenJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
evenJobPermits.acquire();
System.out.println(i * 2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
oddJobPermits.release();
}
}
}
}
private class OddJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
oddJobPermits.acquire();
System.out.println(i * 2 + 1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
evenJobPermits.release();
}
}
}
}
public void run() {
new Thread(new EvenJob()).start();
new Thread(new OddJob()).start();
}
public static void main(String[] args) {
new Test().run();
}
}
I believe you will need a referee:
public class Referee {
private boolean evensTurn = true;
public void waitMyTurn(boolean even) {
synchronized(this) {
while (even != evensTurn) {
try {
wait();
} finally {
}
}
}
}
public void done() {
synchronized(this) {
evensTurn = !evensTurn;
notify();
}
}
}
public class PrintEvenNumbersJob implements Runnable {
private Referee referee;
public PrintEvenNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(true);
System.out.println(i);
referee.done();
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Referee referee;
public PrintOddNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(false);
System.out.println(i);
referee.done();
}
}
}
I tried and tested this code. It works using Semaphore
public class TestSemaphore
{
public static void main(String[] args)
throws Exception
{
AtomicInteger count = new AtomicInteger();
Semaphore s = new Semaphore(1, true);
Semaphore t = new Semaphore(1, true);
OddNumberThread oThread = new OddNumberThread(count, s, t);
EvenNumberThread eThread = new EvenNumberThread(count, s, t);
eThread.start();
oThread.start();
}
static class EvenNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public EvenNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Even");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Make this thread wait until even thread starts, Order will be incorrect if removed these lines.
s.acquireUninterruptibly();
while (count.intValue() <= 10)
{
try
{
// Double checking to make it work
s.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
t.release();
}
}
}
}
static class OddNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public OddNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Odd");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Start this thread first and start printing, Order will be incorrect if removed these lines.
t.acquireUninterruptibly();
s.release();
while (count.intValue() <= 10)
{
try
{
t.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
s.release();
}
}
}
}
}
i have made a program and expecting output like this :
A
1
a
B
2
b
C
3
c
...
E
5
e
here is my code i think am getting starvation problem plz help me
class Product {
static boolean flag1, flag2, flag3;
synchronized void printLwrAlpha(char value) {
// System.out.println(flag3+": inside lwr_alpha");
if (!flag3)
try {
wait();
} catch (Exception ex) {
System.out.println(ex);
}
System.out.println(value);
flag3 = false;
flag1 = false;
System.out.println("before notify");
notify();
System.out.println("after notify");
}
synchronized void printUprAlpha(char n) {
// System.out.println(flag1+": inside upr_alpha");
if (flag1)
try {
wait();
} catch (Exception e) {
System.out.println(e);
}
System.out.println(n);
// System.out.println(num);
flag1 = true;
flag2 = true;
notify();
}
synchronized void printNum(int num) {
// System.out.println(flag2+": inside num");
if (!flag2)
try {
wait();
} catch (Exception e) {
System.out.println(e);
}
// System.out.println(n);
System.out.println(num);
flag2 = false;
flag3 = true;
notify();
}
}
class PrintNum implements Runnable {
Product p;
PrintNum(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++)
p.printNum(i);
}
}
class PrintLwrAlpha implements Runnable {
Product p;
static char ch = 'a';
PrintLwrAlpha(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++) {
char c = (char) (ch + (i - 1));
p.printLwrAlpha(c);
}
}
}
class PrintUprAlpha implements Runnable {
Product p;
static char ch = 'A';
PrintUprAlpha(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++) {
char c = (char) (ch + (i - 1));
p.printUprAlpha(c);
}
}
}
public class MainClass1 {
public static void main(String ar[]) {
Product p = new Product();
new PrintNum(p);
new PrintUprAlpha(p);
new PrintLwrAlpha(p);
}
}
i am getting this output:
run:
A
1
B
2
C
3
D
4
E
5
a
before notify
after notify
i think after this program is going in to starvation
Replace all your ifs, e.g.
if (!flag3)
with while loops
while (!flag3)
If I understand correctly your problem is that you're trying to use a single wait object with multiple threads. The common scenario for wait/notify is as follows: the one thread is waiting for resource to become available while the second thread produces the resource and notifies the first thread.
In code it may look like this:
class ResourceFactory {
public synchronized void produce()
{
// make the resource available
obj.notify();
}
public synchronized void consume()
{
if( /* resource is not available */ ) {
obj.wait();
}
// do something with resource
}
}
When multiple threads are trying to wait on a single object the problem is that it's up to implementation which thread would be awaken after notify call. I think you should make 3 different objects and do something like this:
// thread 1
obj1.wait();
obj2.notify()
// thread 2
obj2.wait();
obj3.notify()
// thread 3
obj3.wait();
obj1.notify()
Be careful and try not to deadlock your code.
And at last your code. First two threads are waiting and awaken each other despite the flags. And when the third thread is awaken there's no thread to notify it. So it's a classical deadlock.
I was attempting to solve a multi threaded problem and I am facing difficulties getting to know its behavior.
The problem is:
There are 2 threads which simultaneously consume even and odd numbers. I have to introduce the thread communication between them to have the "consumption" in natural ordering.
here is my code
public class EvenOddDemo {
public static void main(String[] args) {
Number n = new Number();
EvenThread et = new EvenThread(n);
OddThread ot = new OddThread(n);
et.start();
ot.start();
}
}
class EvenThread extends Thread {
private Number number;
public EvenThread(Number number) {
this.number = number;
}
#Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(number.getEven());
}
}
}
class OddThread extends Thread {
private Number number;
public OddThread(Number number) {
this.number = number;
}
#Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(number.getOdd());
}
}
}
class Number {
private int currentEven = 0;
private int currentOdd = 1;
private volatile String last = "odd";
public synchronized int getEven() {
if("even".equals(last)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = currentEven;
last = "even";
currentEven +=2;
notify();
return i;
}
public synchronized int getOdd() {
if("odd".equals(last)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = currentOdd;
last = "odd";
currentOdd +=2;
notify();
return i;
}
}
and the output is
0
2
1
3
4
5
7
6
8
9
But when I debug the code, it prints the numbers in the correct order. Hence I am not able to figure out what I am missing. Please help me. Thanks in advance for your time for this thread.
As far as I can see, there is nothing preventing this from happening, explaining why 2 is displayed before 1 in your output:
OddThread EvenThread
---------- ----------
gets odd
gets even
prints even
prints odd
The lock therefore needs to be around the whole sequence "get/print".
You'll notice that you are never "two numbers apart" in your output, too.
notify chooses any available thread.
The choice is arbitrary and occurs at the discretion of the implementation
If there are more than two threads waiting you could be signalling the "wrong" thread.
Also, note that both of your threads could be just finished in get(Even|Odd) with neither waiting, leading to the notify going nowhere depending upon the scheduling.
You need to be more strict to ensure the ordering. Perhaps two locks, even and odd, would be helpful.
You need to print the number in getEven and getOdd functions and notify the other thread.
But you were notifying and printing the number, so between noti
Modified code:
public class ThreadExp {
public static void main(String[] args) {
Number n = new Number();
EvenThread et = new EvenThread(n);
OddThread ot = new OddThread(n);
et.start();
ot.start();
}
}
class EvenThread extends Thread {
private Number number;
public EvenThread(Number number) {
this.number = number;
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
number.getEven();
}
}
}
class OddThread extends Thread {
private Number number;
public OddThread(Number number) {
this.number = number;
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
number.getOdd();
}
}
}
class Number {
private int currentEven = 0;
private int currentOdd = 1;
private StringBuilder odd;
private StringBuilder even;
private StringBuilder last;
{
odd = new StringBuilder("odd");
even = new StringBuilder("even");
last = odd;
}
public synchronized void getEven() {
if (last == even) {
try {
//System.out.println("inside if in even--->" +Thread.currentThread());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("out of if in even--> " + Thread.currentThread());
int i = currentEven;
last = even;
currentEven += 2;
System.out.println(i);
notify();
return;
}
public synchronized void getOdd() {
if (last == odd) {
try {
//System.out.println("inside if in odd--->" +Thread.currentThread());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("out of if in odd--> " + Thread.currentThread());
int i = currentOdd;
last = odd;
currentOdd += 2;
System.out.println(i);
notify();
return;
}
}