I have a Java program that is simulating one way tunnel. A semaphore represents the tunnel, and there are two threads that represent the queues of traffic waiting on either side to pass through. In main, both threads are started as well as a thread to generate cars on either side every second. When a thread realizes its queue has cars in it, it attempts to acquire the semaphore. Once it has it, it allows each car to pass through, and releases the semaphore for the other side to use.
My problem is that it only is able to pass cars on the first try. After one side has claimed and released the semaphore, it seems that it will not be able to send cars through again. It seems to be that the if statement that is checking for cars in the queue is not executing.
class leftManager extends Thread {
private int leftQueue = 0;
private int total = 0;
static Semaphore semaphore;
public leftManager(Semaphore semaphore) {
this.semaphore = semaphore;
this.leftQueue = leftQueue;
}
public int getQueue() {
return leftQueue;
}
public void setQueue(int x) {
leftQueue += x;
}
#Override
public void run() {
try {
while (true) {
if (leftQueue > 0) {
System.out.println("Catch");
semaphore.acquire();
for (int i = 1; i <= leftQueue; i++) {
int temp = (leftQueue - (leftQueue - (i - 1)));
leftBoundPass pass = new leftBoundPass((temp * 2) + total);
pass.start();
try {
leftManager.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
total += leftQueue;
leftQueue = 0;
semaphore.release();
System.out.println("release");
}
else {
continue;
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The rightManager is identical, other than different variable names and a different "boundPass" thread for the cars.
class leftBoundPass extends Thread {
private int car;
public leftBoundPass(int car) {
this.car = car;
}
#Override
public void run() {
System.out.println("Left-bound car " + car + " is in the tunnel.");
//This is one second of sleep
try {
leftBoundPass.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Left-bound car " + car + " is exiting the tunnel.");
}
}
The car generator is as follows:class trafficGenerator extends Thread {
leftManager left;
rightManager right;
public trafficGenerator(leftManager left, rightManager right) {
this.left = left;
this.right = right;
}
#Override
public void run() {
int random;
while (true) {
random = (int)(Math.random() * 2);
if (random == 0) {
System.out.println("Left-bound car wants to enter the tunnel");
left.setQueue(1);
//System.out.println(left.getQueue());
}
else {
System.out.println("Right-bound car wants to enter the tunnel");
right.setQueue(1);
}
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
System.err.println(e);
}
}
}
}
Output:
Left-bound car wants to enter the tunnel
Catch
Left-bound car 0 is in the tunnel.
Left-bound car 0 is exiting the tunnel.
release
Left-bound car wants to enter the tunnel
Right-bound car wants to enter the tunnel
Right-bound car wants to enter the tunnel
I created a project for studying purposes that simulates a restaurant service using Threads. There is a Thread for Cook(s) to prepare a meal and another Thread for Waiter(s) to serve the meal. When I tested it with 1 cook and 5 waiters, it worked fine. But when I increase the number of cooks, the program runs indefinitely. What is wrong? Here is the code:
Class Main
package restaurant;
import java.util.concurrent.Semaphore;
public class Main {
public static int MAX_NUM_MEALS = 5;
public static int OLDEST_MEAL = 0;
public static int NEWEST_MEAL = -1;
public static int DONE_MEALS = 0;
public static int NUM_OF_COOKS = 1;
public static int NUM_OF_WAITERS = 5;
public static Semaphore mutex = new Semaphore(1);
static Cook cookThreads[] = new Cook[NUM_OF_COOKS];
static Waiter waiterThreads[] = new Waiter[NUM_OF_WAITERS];
public static void main(String[] args) {
for(int i = 0; i < NUM_OF_COOKS; i++) {
cookThreads[i] = new Cook(i);
cookThreads[i].start();
}
for(int i = 0; i < NUM_OF_WAITERS; i++) {
waiterThreads[i] = new Waiter(i);
waiterThreads[i].start();
}
try {
for(int i = 0; i < NUM_OF_COOKS; i++) {
cookThreads[i].join();
}
for(int i = 0; i < NUM_OF_WAITERS; i++) {
waiterThreads[i].join();
}
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("All done");
}
}
Class Cook
package restaurant;
public class Cook extends Thread{
private int id;
public Cook(int id) {
this.id = id;
}
public void run() {
while(true) {
System.out.println("Cook " + id + " is prepearing meal");
try {
Thread.sleep(1000);
Main.mutex.acquire();
Main.NEWEST_MEAL++;
Main.mutex.release();
Main.mutex.acquire();
Main.DONE_MEALS++;
Main.mutex.release();
System.out.println("Cook " + id + " has finished the meal");
if(Main.DONE_MEALS == 5) {
System.out.println("Cook " + id + " has finished his job");
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Class Waiter
package restaurant;
public class Waiter extends Thread{
private int id;
public Waiter(int id) {
this.id = id;
}
public void run() {
while(true) {
System.out.println("Waiter " + id + " will check if there is any meal to serve");
if(Main.NEWEST_MEAL >= Main.OLDEST_MEAL) {
try {
Main.mutex.acquire();
Main.OLDEST_MEAL++;
Main.mutex.release();
System.out.println("Waiter " + id + " is picking up meal");
Thread.sleep(500);
System.out.println("Waiter " + id + " has delivered the meal to client");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(Main.DONE_MEALS == 5) {
System.out.println("Waiter " + id + " has finished his job");
break;
}
System.out.println("No meal to serve. Waiter " + id + " will come back later");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Two issues:
Because you have two cooks, one of your cooks likely won't see Main.DONE_MEALS == 5. It will jump from 4 to 6 because of the other cook. Instead, check for Main.DONE_MEALS >= 5.
There is no guarantee that the cook or waiter threads will see the updates to Main.DONE_MEALS. Instead, consider having a private static final AtomicInteger field. The AtomicInteger class is a thread-safe integer implementation that enables other threads to see it in a thread-safe way.
The traditional fix would be:
a) You have to use the lock (mutex) not only when you write, but also when you read - otherwise it won't work correctly.
Just imagine you agreed on a signal to indicate if the bathroom is busy, but some just decide to ignore it - won't work!.
b) Check the condition before you do something.
Once you acquire the lock, you don't know the state so you should first check it before you proceed to make another meal. If you first check if there are already 5 done meals and only produce meals if there aren't yet 5, it should fix this problem, and you should only ever see done_meals <= 5 (you should review other parts of the code because it has similar problems, though).
Like others have mentioned, there are cleaner ways to write this but IMO your code is very suited for practice and understanding, so I'd try that rather than jumping for things like AtomicInteger.
While I do understand the Gist of inter thread communication and the usage of wait and notify on the monitor to ensure Put/Get operations are synchronized - I'm trying to understand why we need the Thread.sleep() in the code below for both producer and consumer when we have a working wait/notify mechanism? If I remove the thread.sleep() - the output goes to hell!
import java.io.*;
import java.util.*;
public class Test {
public static void main(String argv[]) throws Throwable {
Holder h = new Holder();
Thread p = new Thread(new Producer(h), "Producer");
Thread c = new Thread(new Consumer(h), "Consumer");
p.start();
c.start();
}
}
class Holder {
int a;
volatile boolean hasPut;
public synchronized void put(int i) {
while (hasPut) {
try {
System.out.println("The thread " + Thread.currentThread().getName() + " Going ta sleep...");
wait(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
this.a = i;
hasPut = true;
notifyAll();
}
public synchronized int get() {
while (!hasPut) {
try {
System.out.println("The thread " + Thread.currentThread().getName() + " Going ta sleep...");
wait(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
hasPut = false;
notifyAll();
return this.a;
}
}
class Producer implements Runnable {
Holder h;
public Producer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("Putting : "+i);
h.put(i);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
}
}
}
}
class Consumer implements Runnable {
Holder h;
public Consumer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
int k = h.get();
System.out.println("Getting : "+k);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
}
}
}
}
I think you get confused by the console output.
The important part is if every .get() in the consumer gets all the elements from the producer.
When you remove all the confusing System.out. lines and just use
class Consumer implements Runnable {
Holder h;
public Consumer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
int k = h.get();
if (k != i)
System.out.println("Got wrong value " + k + "expected value " + i);
}
}
}
You will see that your code works fine.
I think your confusion comes from outputs that looks like this
Getting : 990
Putting : 993
Getting : 991
Getting : 992
The thread Consumer Going ta sleep...
Getting : 993
But also you see all the gets are in the right order and all the puts too.
So this is a problem of the way in which the output works in Java, when multiple threads are involved.
One thread will read the data & the iteration may take more than the number of times the data fetched.
Since all the threads concurrently access the data & processes it more than expected number of times, there should be Thread.sleep for certain milliseconds.
I faced the same issue, where after increasing thread.sleep() it read once & processed once
I have tired this question, and i ended up with some doubts. Please help me out
Doubt : If any thread is in wait state , and no other thread is notifying that one , so will it never come to and end ? Even after using wait(long milliseconds).
For Code : What my requirement is from the code(Please Refer My Code) :
a : Should print "Even Thread Finish " and "Odd Thread Finish" (Order is not imp , but must print both)
b: Also in main function should print " Exit Main Thread"
What is actually happening :
After lot of runs , in some cases , it prints "Even Thread Finish" then hangs here or vice-versa. In some cases it prints both.
Also it never prints "Exit Main Thread".
So How to modify code , so it must print all 3 statement .(Of Course "Exit Main.. " in last , as i am using join for main.)
In brief : Main start-> t1 start -> t2 start ,, then i need t2/t1 finish -> main finish.
Please help me out for this problem
Here is my code :
import javax.sql.CommonDataSource;
public class ThreadTest {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Share commonObj = new Share();
Thread even = new Thread(new EvenThread(commonObj));
Thread odd = new Thread(new OddThread(commonObj));
even.start();
odd.start();
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Exit Main Thread");
}
}
class EvenThread implements Runnable {
private Share commShare;
public EvenThread(Share obj) {
// TODO Auto-generated constructor stub
this.commShare = obj;
}
private int number = 2;
public void run() {
System.out.println("Even Thread start");
while (number <= 50) {
if (commShare.flag == true) {
System.out.println("Even Thread" + number);
number += 2;
commShare.flag = false;
synchronized(commShare) {
try {
commShare.notify();
commShare.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
commShare.notify();
}
} else {
synchronized(commShare) {
try {
commShare.notify();
commShare.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
commShare.notify();
}
}
}
System.out.println("Even Thread Finish");
}
}
class OddThread implements Runnable {
private int number = 1;
private Share commShare;
public OddThread(Share obj) {
// TODO Auto-generated constructor stub
this.commShare = obj;
}
public void run() {
System.out.println("Odd Thread start");
while (number <= 50) {
if (commShare.flag == false) {
System.out.println("Odd Thread :" + number);
number += 2;
commShare.flag = true;
synchronized(commShare) {
try {
commShare.notify();
commShare.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
commShare.notify();
}
}
}
System.out.println("Odd Thread Finish");
}
}
class Share {
Share sharedObj;
public boolean flag = false;
}
Although this is not the exact answer of your question, but this implementation is an alternative of your problem .
public class EvenOddThreads {
public static void main(String[] args) {
Thread odd = new Thread(new OddThread(), "oddThread");
Thread even = new Thread(new EvenThread(), "Even Thread");
odd.start();
even.start();
try {
odd.join();
even.join();
System.out.println("Main thread exited");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class OddThread implements Runnable{
public void run() {
synchronized (CommonUtil.mLock) {
System.out.println(Thread.currentThread().getName()+"---> job starting");
int i = 1;
while(i<50){
System.out.print(i + "\t");
i = i + 2;
CommonUtil.mLock.notify();
try {
CommonUtil.mLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("OddThread---> job completed");
CommonUtil.mLock.notify();
}
}
}
class EvenThread implements Runnable{
#Override
public void run() {
synchronized (CommonUtil.mLock) {
System.out.println(Thread.currentThread().getName()+"---> job started");
int i =2;
while(i<50){
System.out.print(i + "\t");
i = i+2;
CommonUtil.mLock.notify();
try {
CommonUtil.mLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("EvenThread---> job completed");
CommonUtil.mLock.notify();
}
}
}
class CommonUtil{
static final Object mLock= new Object();
}
Output:
oddThread---> job starting
1 Even Thread---> job started
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 EvenThread---> job completed
OddThread---> job completed
Main thread exited
Well, I have spent last three hours reading a Java sychronization tutorial (a very good one) followed by more info about wait, notify and notifyAll, and i ended up with program that uses N threads to count from A to B, set N to 2 and you have odd and even.
pastebin
Also, my program has no comments whatsoever, so make sure you read the tutorial(s) before you try understand this code.
Also it never prints "Exit Main Thread".
That is because maybe because your threads are waiting on the lock for someone to notify() but due to missed signal or no one signalling them, they never get out of waiting state. For that the best solution is to use:
public final void wait(long timeout)
throws InterruptedException
Causes the current thread to wait until either another thread invokes
the notify() method or the notifyAll() method for this object, or a
specified amount of time has elapsed.
This overloaded method will wait for other thread to notify for specific amount of time and then return if timeout occurs. So in case of a missed signal the thread will still resume its work.
NOTE: After returning from wait state always check for
PRE-CONDITION again, as it can be a Spurious Wakeup.
Here is my flavor of program that I coded some time back for the same.
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
private static int range = 10;
private static volatile AtomicInteger present = new AtomicInteger(0);
private static Object lock = new Object();
public static void main(String[] args) {
new Thread(new OddRunnable()).start();
new Thread(new EvenRunnable()).start();
}
static class OddRunnable implements Runnable{
#Override
public void run() {
while(present.get() <= range){
if((present.get() % 2) != 0){
System.out.println(present.get());
present.incrementAndGet();
synchronized (lock) {
lock.notifyAll();
}
}else{
synchronized (lock) {
try {
lock.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
}
}
static class EvenRunnable implements Runnable{
#Override
public void run() {
while(present.get() <= range){
if((present.get() % 2) == 0){
System.out.println(present.get());
present.incrementAndGet();
synchronized (lock) {
lock.notifyAll();
}
}else{
synchronized (lock) {
try {
lock.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
}
}
}
See the solution, I have kept a lock that works for notifying the chance of even or odd thread. If even thread finds that the present number is not even it waits on the lock and
hopes that odd thread will notify it when it prints that odd number. And similarly it works for odd thread too.
I am not suggesting that this is the best solution but this is something that came out in the first try, some other options are also possible.
Also I would like to point out that this question though as a practice is good, but do keep in mind that you are not doing anything parallel there.
This could be an exercise on threads and lock monitors, but there is nothing to do in parallel that give you advantages.
In your code when a thread 1 (OddThread or EvenThread) ends his work and prints out "Odd Thread Finish" (or "Even Thread Finish") the other thread 2 is waiting a notify() or a notifyAll() that never will happen because the first is over.
You have to change EvenThread and OddThread adding a synchronized block with a notify call on commShare just after the while cycle. I removed the second if-branch because in this way you don't continue to check the while condition but get a wait on commShare soon.
class EvenThread implements Runnable {
private Share commShare;
private int number = 2;
public EvenThread(Share obj) {
this.commShare = obj;
}
public void run() {
System.out.println("Even Thread start");
while (number <= 50) {
synchronized (commShare) {
if (commShare.flag) {
System.out.println("Even Thread:" + number);
number += 2;
commShare.flag = false;
}
commShare.notify();
try {
commShare.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized (commShare) {
commShare.notify();
System.out.println("Even Thread Finish");
}
}
}
class OddThread implements Runnable {
private int number = 1;
private Share commShare;
public OddThread(Share obj) {
this.commShare = obj;
}
public void run() {
System.out.println("Odd Thread start");
while (number <= 50) {
synchronized (commShare) {
if (!commShare.flag) {
System.out.println("Odd Thread: " + number);
number += 2;
commShare.flag = true;
}
commShare.notify();
try {
commShare.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized (commShare) {
commShare.notify();
System.out.println("Odd Thread Finish");
}
}
Finally, in the main you have to join for each thread you started. It's sure that Thread.currentThread() returns just one of yours threads? We have started two threads and those threads we should join.
try {
even.join();
odd.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I will not vote for using wait() and notify(). The things that you can do with wait and notify can be done through more sophisticated tools like semaphore, countDownLatch, CyclicBarrier. You can find this advice in the famous book Effective java in item number 69 prefer concurrency utilities to wait and notify.
Even in this case we don't need this things at all, we can achieve this functionality by a simple volatile boolean variable. And for stopping a thread the best possible way is to use interrupt. After certain amount of time or some predefined condition we can interrupt threads. Please find my implementation attached:
Thread 1 for printing even numbers:
public class MyRunnable1 implements Runnable
{
public static volatile boolean isRun = false;
private int k = 0 ;
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
if(isRun){
System.out.println(k);
k+=2;
isRun=false;
MyRunnable2.isRun=true;
}
}
}
}
Thread 2 for printing even numbers:
public class MyRunnable2 implements Runnable{
public static volatile boolean isRun = false;
private int k = 1 ;
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
if(isRun){
System.out.println(k);
k+=2;
isRun=false;
MyRunnable1.isRun=true;
}
}
}
}
Now main method which drives the above threads
public class MyMain{
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(new MyRunnable1());
Thread t2 = new Thread(new MyRunnable2());
MyRunnable1.isRun=true;
t1.start();
t2.start();
Thread.currentThread().sleep(1000);
t1.interrupt();
t2.interrupt();
}
}
There may be some places you need to change a bit this is just a skeletal implementation. Hope it helps and please let me know if you need something else.
public class PrintNumbers {
public static class Condition {
private boolean start = false;
public boolean getStart() {
return start;
}
public void setStart(boolean start) {
this.start = start;
}
}
public static void main(String[] args) {
final Object lock = new Object();
// condition used to start the odd number thread first
final Condition condition = new Condition();
Thread oddThread = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
for (int i = 1; i <= 10; i = i + 2) { //For simplicity assume only printing till 10;
System.out.println(i);
//update condition value to signify that odd number thread has printed first
if (condition.getStart() == false) {
condition.setStart(true);
}
lock.notify();
try {
if (i + 2 <= 10) {
lock.wait(); //if more numbers to print, wait;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread evenThread = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
for (int i = 2; i <= 10; i = i + 2) { //For simplicity assume only printing till 10;
// if thread with odd number has not printed first, then wait
while (condition.getStart() == false) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
lock.notify();
try {
if (i + 2 <= 10) { //if more numbers to print, wait;
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
oddThread.start();
evenThread.start();
}
}
I did it using ReentrantLock with 25 threads . One thread Print One number and it will notify to other .
public class ReentrantLockHolder
{
private Lock lock;
private Condition condition;
public ReentrantLockHolder(Lock lock )
{
this.lock=lock;
this.condition=this.lock.newCondition();
}
public Lock getLock() {
return lock;
}
public void setLock(Lock lock) {
this.lock = lock;
}
public Condition getCondition() {
return condition;
}
public void setCondition(Condition condition) {
this.condition = condition;
}
}
public class PrintThreadUsingReentrantLock implements Runnable
{
private ReentrantLockHolder currHolder;
private ReentrantLockHolder nextHolder;
private PrintWriter writer;
private static int i=0;
public PrintThreadUsingReentrantLock(ReentrantLockHolder currHolder, ReentrantLockHolder nextHolder ,PrintWriter writer)
{
this.currHolder=currHolder;
this.nextHolder=nextHolder;
this.writer=writer;
}
#Override
public void run()
{
while (true)
{
writer.println(Thread.currentThread().getName()+ " "+ ++i);
try{
nextHolder.getLock().lock();
nextHolder.getCondition().signal();
}finally{
nextHolder.getLock().unlock();
}
try {
currHolder.getLock().lock();
currHolder.getCondition().await();
}catch (InterruptedException e)
{
e.printStackTrace();
}
finally{
currHolder.getLock().unlock();
}
}
}
}
public static void main(String[] args)
{
PrintWriter printWriter =null;
try {
printWriter=new PrintWriter(new FileOutputStream(new File("D://myFile.txt")));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ReentrantLockHolder obj[]=new ReentrantLockHolder[25];
for(int i=0;i<25;i++)
{
obj[i]=new ReentrantLockHolder(new ReentrantLock());
}
for(int i=0;i<25;i++)
{
Thread t1=new Thread(new PrintThreadUsingReentrantLock(obj[i], obj[i+1 == 25 ? 0 : i+1],printWriter ),"T"+i );
t1.start();
}
}
I tried the similar stuff where Thread 1 prints Odd numbers and Thread 2 prints even numbers in a correct order and also when the printing is over, the desired messages as you had suggested will be printed. Please have a look at this code
package practice;
class Test {
private static boolean oddFlag = true;
int count = 1;
private void oddPrinter() {
synchronized (this) {
while(true) {
try {
if(count < 10) {
if(oddFlag) {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ": " + count++);
oddFlag = !oddFlag;
notifyAll();
}
else {
wait();
}
}
else {
System.out.println("Odd Thread finished");
notify();
break;
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void evenPrinter() {
synchronized (this) {
while (true) {
try {
if(count < 10) {
if(!oddFlag) {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ": " + count++);
oddFlag = !oddFlag;
notify();
}
else {
wait();
}
}
else {
System.out.println("Even Thread finished");
notify();
break;
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException{
final Test test = new Test();
Thread t1 = new Thread(new Runnable() {
public void run() {
test.oddPrinter();
}
}, "Thread 1");
Thread t2 = new Thread(new Runnable() {
public void run() {
test.evenPrinter();
}
}, "Thread 2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Main thread finished");
}
}
package test;
public class Interview2 {
public static void main(String[] args) {
Obj obj = new Obj();
Runnable evenThread = ()-> {
synchronized (obj) {
for(int i=2;i<=50;i+=2) {
while(!obj.printEven) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
obj.printEven = false;
obj.notify();
}
}
};
Runnable oddThread = ()-> {
synchronized (obj) {
for(int i=1;i<=49;i+=2) {
while(obj.printEven) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
obj.printEven = true;
obj.notify();
}
}
};
new Thread(evenThread).start();
new Thread(oddThread).start();
}
}
class Obj {
boolean printEven;
}
This is very generic solution. It uses semaphores to do signaling among threads.
This is general solution where N threads prints M natural numbers in sequence turn by turn.
that is if we have 3 threads and we want to print 7 natural numbers, output would be:
Thread 1 : 1
Thread 2 : 2
Thread 3 : 3
Thread 1 : 4
Thread 2 : 5
Thread 3 : 6
Thread 1 : 7
import java.util.concurrent.Semaphore;
/*
* Logic is based on simple idea
* each thread should wait for previous thread and then notify next thread in circular fashion
* There is no locking required
* Semaphores will do the signaling work among threads.
*/
public class NThreadsMNaturalNumbers {
private static volatile int nextNumberToPrint = 1;
private static int MaxNumberToPrint;
public static void main(String[] args) {
int numberOfThreads = 2;
MaxNumberToPrint = 50;
Semaphore s[] = new Semaphore[numberOfThreads];
// initialize Semaphores
for (int i = 0; i < numberOfThreads; i++) {
s[i] = new Semaphore(0);
}
// Create threads and initialize which thread they wait for and notify to
for (int i = 1; i <= numberOfThreads; i++) {
new Thread(new NumberPrinter("Thread " + i, s[i - 1], s[i % numberOfThreads])).start();
}
s[0].release();// So that First Thread can start Processing
}
private static class NumberPrinter implements Runnable {
private final Semaphore waitFor;
private final Semaphore notifyTo;
private final String name;
public NumberPrinter(String name, Semaphore waitFor, Semaphore notifyTo) {
this.waitFor = waitFor;
this.notifyTo = notifyTo;
this.name = name;
}
#Override
public void run() {
while (NThreadsMNaturalNumbers.nextNumberToPrint <= NThreadsMNaturalNumbers.MaxNumberToPrint) {
waitFor.acquireUninterruptibly();
if (NThreadsMNaturalNumbers.nextNumberToPrint <= NThreadsMNaturalNumbers.MaxNumberToPrint) {
System.out.println(name + " : " + NThreadsMNaturalNumbers.nextNumberToPrint++);
notifyTo.release();
}
}
notifyTo.release();
}
}
}
This Class prints Even Number:
public class EvenThreadDetails extends Thread{
int countNumber;
public EvenThreadDetails(int countNumber) {
this.countNumber=countNumber;
}
#Override
public void run()
{
for (int i = 0; i < countNumber; i++) {
if(i%2==0)
{
System.out.println("Even Number :"+i);
}
try {
Thread.sleep(2);
} catch (InterruptedException ex) {
// code to resume or terminate...
}
}
}
}
This Class prints Odd Numbers:
public class OddThreadDetails extends Thread {
int countNumber;
public OddThreadDetails(int countNumber) {
this.countNumber=countNumber;
}
#Override
public void run()
{
for (int i = 0; i < countNumber; i++) {
if(i%2!=0)
{
System.out.println("Odd Number :"+i);
}
try {
Thread.sleep(2);
} catch (InterruptedException ex) {
// code to resume or terminate...
}
}
}
}
This is Main class:
public class EvenOddDemo {
public static void main(String[] args) throws InterruptedException
{
Thread eventhread= new EvenThreadDetails(100);
Thread oddhread=new OddThreadDetails(100);
eventhread.start();
oddhread.start();
}
}
I have done it this way and its working...
class Printoddeven{
public synchronized void print(String msg){
try {
if(msg.equals("Even"))
{
for(int i=0;i<=10;i+=2){
System.out.println(msg+" "+i);
Thread.sleep(2000);
notify();
wait();
}
}
else{
for(int i=1;i<=10;i+=2){
System.out.println(msg+" "+i);
Thread.sleep(2000);
notify();
wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class PrintOdd extends Thread{
Printoddeven oddeven;
public PrintOdd(Printoddeven oddeven){
this.oddeven=oddeven;
}
public void run(){
oddeven.print("ODD");
}
}
class PrintEven extends Thread{
Printoddeven oddeven;
public PrintEven(Printoddeven oddeven){
this.oddeven=oddeven;
}
public void run(){
oddeven.print("Even");
}
}
public class mainclass
{
public static void main(String[] args)
{
Printoddeven obj = new Printoddeven();//only one object
PrintEven t1=new PrintEven(obj);
PrintOdd t2=new PrintOdd(obj);
t1.start();
t2.start();
}
}
public class Driver {
static Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int itr = 1; itr < 51; itr = itr + 2) {
synchronized (lock) {
System.out.print(" " + itr);
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("\nEven Thread Finish ");
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
for (int itr = 2; itr < 51; itr = itr + 2) {
synchronized (lock) {
System.out.print(" " + itr);
try {
lock.notify();
if(itr==50)
break;
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("\nOdd Thread Finish ");
}
});
try {
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Exit Main Thread");
} catch (Exception e) {
}
}
}
I have a program that simulates Gates to a ship. They run in threads. The idea is to let them run and pause during a random moment in the run method to simulate persons passing. This is done by all threads, meanwhile the main thread is waiting for notification and checking if the ship is getting full when notified by the threads that they added a person passing through the gate the main thread checks again if the ship is full. The program has three classes:
A counter:
public class Counter {
private int currentValue[];
private int maxValue;
public Counter(int[] nrOfPeople, int max) {
currentValue = nrOfPeople;
currentValue[0] = 0;
maxValue = max;
}
public synchronized void addPersons(int nr_p) {
currentValue[0] += nr_p;
}
public synchronized int getValue() {
return currentValue[0];
}
public synchronized boolean isFull() {
if(currentValue[0] < maxValue)
return false;
return true;
}
}
A Gate Class:
public abstract class Gate implements Runnable {
int nrOfPassengers;
int gatenr;
int gatesize;
Counter c;
private Thread t;
private Random r;
private boolean blocked; /* suspends people from passing */
public Gate(Counter c, int nr) {
this.c = c;
gatenr = nr;
this.open();
r = new Random();
t = new Thread(this);
t.start();
}
public void setGatesize(int size) {
gatesize = size;
}
public void close() {
blocked = true;
}
public void open() {
blocked = false;
}
public int getNoOfPassangers() {
return nrOfPassengers;
}
public int getId() {
return gatenr;
}
#Override
public void run() {
while(!blocked) {
int waitTime = (r.nextInt(5) + 1) * 1000; /* between 1-5 seconds */
System.out.println("Person-Gate " + gatenr + ": adding one to " + c.getValue());
try {
/* bigger throughput => amount can vary */
if(gatesize > 1) {
int persons = r.nextInt(gatesize)+1;
c.addPersons(persons);
nrOfPassengers += persons;
} else {
c.addPersons(1);
nrOfPassengers++;
}
Thread.sleep(waitTime);
} catch (InterruptedException e) {
System.out.println("Person-Gate " + gatenr + ": was interrupted adding person");
e.printStackTrace();
}
System.out.println("Person-Gate " + gatenr + ": added one to " + c.getValue());
t.notify();
}
}
public void join() {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And a Simulator that runs the main method:
/*
* This class simulates cars and persons- entering a ferry.
*/
public class Simulator {
public static final int MAX = 30;
public static void main(String[] args) {
int nrOfPeople[] = new int[1]; /* array of size one for keeping count */
ArrayList<Gate> gates = new ArrayList<Gate>();
Counter counter = new Counter(nrOfPeople, MAX);
Thread mainThread = Thread.currentThread();
/* adding 3 person-gates */
for(int i=1; i<4; i++) {
gates.add(new PersonGate(counter, i));
}
/* let all gates work as long as passengers is under MAX */
while(!counter.isFull()) {
try {
mainThread.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Announcement: Ship is full!");
/* wait for child threads to finish */
for(Gate g: gates) {
g.close();
try {
g.join();
} catch (Exception e) { /* InterruptedException */
e.printStackTrace();
}
System.out.println(g.getNoOfPassangers() + " passed through gate nr " + g.getId());
System.out.println(counter.getValue() + " has passed in total");
}
}
}
Im getting a error
Person-Gate 1: adding one to 0
Person-Gate 2: adding one to 1
Person-Gate 3: adding one to 2
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at Simulator.main(Simulator.java:24)
Person-Gate 3: added one to 3Exception in thread "Thread-3"
Does anyone now whats going on?
You can only call wait and notify/notifyAll from within synchronized blocks.
t.notify();
You are notifying wrong monitor. This exception occurs, when you do not wrap monitor object with synchronize section. However, objects which you are using for notify and for wait methods are different. Create new Object() monitor and pass it to the constructor of Gate.
Also you can take a look at CountDownLatch, it does exactly what you are trying to achieve.
You must own the monitor of the object on which you call wait or notify. Meaning, you must be in a synchonize-Block, like
synchronized( objectUsedAsSynchronizer) {
while ( mustStillWait) {
objectUsedAsSynchronizer.wait();
}
}
This has been the subject of many other questions.