I write a Java program to solve Producer Consumer problem in Multi-Threads. But it can not work correctly.
The program:
public class ConsumerAndProducer {
static int products = 0;
static int capacity = 10;
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
static class Consumer implements Runnable{
public void consume() {
synchronized (ConsumerAndProducer.class){
if(products <= 0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer, remain:" + products);
if(products == 9){
notify();
}
}
}
#Override
public void run() {
while(true){
consume();
}
}
}
static class Producer implements Runnable{
public void produce() {
synchronized (ConsumerAndProducer.class){
if(products == capacity){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer, remain:" + products);
if(products == 1){
notify();
}
}
}
#Override
public void run() {
while(true){
produce();
}
}
}
And the errors:
Producer, remain:1
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at zhousai.ConsumerAndProducer$Producer.produce(ConsumerAndProducer.java:69)
at zhousai.ConsumerAndProducer$Producer.run(ConsumerAndProducer.java:77)
at java.lang.Thread.run(Thread.java:748)
Consumer, remain:0
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at zhousai.ConsumerAndProducer$Consumer.consume(ConsumerAndProducer.java:22)
at zhousai.ConsumerAndProducer$Consumer.run(ConsumerAndProducer.java:43)
at java.lang.Thread.run(Thread.java:748)
When I ran your code, I got the following error:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner
The line of your code throwing that exception is the call to method wait().
You are calling method wait() of class Producer but you are synchronizing on ConsumerAndProducer.class. The wait() method must be called on the object that you are synchronizing on, because that object owns the lock and you must call wait() on the object that owns the lock. Hence the error message: current thread not owner.
The simplest solution is to change your code such that you call ConsumerAndProducer.class.wait() rather than just wait().
Here is your code with my suggested fix:
public class ConsumerAndProducer {
static int products = 0;
static int capacity = 10;
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
static class Consumer implements Runnable {
public void consume() {
synchronized (ConsumerAndProducer.class){
if (products <= 0) {
try {
ConsumerAndProducer.class.wait(); // change here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer, remain:" + products);
if(products == 9){
ConsumerAndProducer.class.notify(); // change here
}
}
}
#Override
public void run() {
while(true){
consume();
}
}
}
static class Producer implements Runnable{
public void produce() {
synchronized (ConsumerAndProducer.class){
if (products == capacity) {
try {
ConsumerAndProducer.class.wait(); // change here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer, remain:" + products);
if(products == 1){
ConsumerAndProducer.class.notify(); // change here
}
}
}
#Override
public void run() {
while(true){
produce();
}
}
}
}
I am trying to create a solution for Producer/ Consumer problem where one thread is putting message in Vector and another is removing from it.
import java.util.Vector;
public class Producer implements Runnable {
static final int MAXQUEUE = 5;
private Vector<String> messages;
public Producer(Vector<String> messages) {
super();
this.messages = messages;
}
#Override
public void run() {
try {
while (true)
putMessage();
} catch (InterruptedException e) {
}
}
private synchronized void putMessage() throws InterruptedException {
while (messages.size() == MAXQUEUE) {
wait();
}
messages.addElement(new java.util.Date().toString());
System.out.println("put message");
notifyAll();
}
public static void main(String args[]) {
Vector<String> messages = new Vector<String>();
new Thread(new Producer(messages)).start();
new Thread(new Consumer(messages)).start();
}
}
class Consumer implements Runnable{
public Consumer(Vector<String> messages) {
super();
this.messages = messages;
}
private Vector<String> messages;
public synchronized String getMessage() throws InterruptedException {
notifyAll();
while (messages.size() == 0) {
wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
}
String message = (String) messages.firstElement();
messages.removeElement(message);
return message;
}
#Override
public void run() {
try {
while (true) {
String message = getMessage();
System.out.println("Got message: " + message);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Whenever I am running the program, it is printing put message 5 times. I don't understand even after notifyAll(), it is not giving lock to consumer.
Your code is not working because your two threads are not notifying/waiting on the same monitor.
They each notify and wait on their own monitor, not a shared monitor. Change code to use a shared monitor, e.g. messages, including the synchronizations.
private void putMessage() throws InterruptedException {
synchronized (messages) { // <======
while (messages.size() == MAXQUEUE) {
messages.wait(); // <======
}
messages.addElement(new java.util.Date().toString());
System.out.println("put message");
messages.notifyAll(); // <======
}
}
public String getMessage() throws InterruptedException {
synchronized (messages) { // <======
while (messages.size() == 0) {
messages.wait(); // <======
}
String message = (String) messages.firstElement();
messages.removeElement(message);
messages.notifyAll(); // <======
return message;
}
}
Notice that methods are no longer synchronized.
Logging to the console is very slow so if you do this without holding the lock you give the consumer a chance.
#Override
public void run() {
try {
while (true) {
// slows the producer a little to give the consumer a chance to get the lock.
System.out.println("put message");
putMessage();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void putMessage() throws InterruptedException {
synchronized (messages) {
while (messages.size() == MAXQUEUE) {
messages.wait();
}
messages.addElement(new java.util.Date().toString());
messages.notifyAll();
}
}
BTW on the consumer you can write this
public String getMessage() throws InterruptedException {
synchronized (messages) {
while (messages.isEmpty()) {
messages.wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
}
messages.notifyAll();
return messages.remove(0);
}
}
I am trying to write a producer consumer program in Java where producer inserts 3 numbers in a Queue and Consumer removes these numbers from the queue. I have implemented my own Queue based on my own Linkedlist implementation.
When I run my code my producer terminates but my consumer never terminates. I am not able to figure out why
public class ProdConMain {
public static void main(String[] args) throws InterruptedException {
MyQueue queue = new MyQueue();
queue.setLimit(3);
Thread producer = new Thread(new Producer(queue));
Thread consumer = new Thread(new Consumer(queue));
producer.start();
consumer.start();
try {
producer.join();
System.out.println("Producer: " + producer.getState());
consumer.join();
System.out.println("Consumer: " + consumer.getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(queue.list.toString());
}
}
public class Producer implements Runnable {
MyQueue queue = new MyQueue();
Random random = new Random();
public Producer(MyQueue queue) {
this.queue = queue;
}
#Override
public void run() {
int i = 1;
while (i < 10) {
synchronized (queue) {
if (queue.getSize() < queue.getLimit()) {
int value = random.nextInt(500);
queue.enqueue(value);
System.out.println("Inserted: " + value);
queue.notify();
} else {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
i++;
}
}
}
public class Consumer implements Runnable {
MyQueue queue = new MyQueue();
public Consumer(MyQueue queue) {
this.queue = queue;
}
#Override
public void run() {
while (true) {
synchronized (queue) {
if (queue.isEmpty()) {
{
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
int value = queue.dequeue();
System.out.println("Removed: " + value);
queue.notify();
}
}
}
}
}
You need to add a stop condition to that while(true) loop in the consumer, otherwise it will never finish. You can do it in the while condition itself:
while(shouldConsume()) {
// consume ...
}
or by breaking the infinite loop if the condition is reached:
while(true) {
// consume ...
if (shouldStopConsume()) {
break;
}
}
And then you just have to implement those methods with the stop condition that fits your use case.
I am learning multithreading. I am implementing producer and consumer problem. I am stuck on scenario where i want that when I press anything apart from integer from keyboard, all my threads should die and there is no memory in use by threads. Please have your valuable inputs to help me achieve it. Below is all the code I am using.
package com.java.concurrency;
public class ThreadSignaling {
private int i = -1;
private boolean valueSet = false;
private boolean stopFlag = false;
public void put(int value) {
synchronized (this) {
while (valueSet) {
if (stopFlag) {
System.out.println("Byeeeeeeeeeeeee");
break;
}
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException while waiting in put() : " + e);
}
}
this.i = value;
this.valueSet = true;
System.out.println("Value put : " + this.i);
this.notify();
}
}
public void get() {
synchronized (this) {
while (!valueSet) {
if (stopFlag) {
System.out.println("Byeeeeeeeeeeeee");
break;
}
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException while waiting in get() : " + e);
}
}
System.out.println("Value get : " + this.i);
valueSet = false;
this.notify();
}
}
public void finish() {
synchronized (this) {
stopFlag = true;
this.notifyAll();
}
}
}
public class Producer implements Runnable {
private ThreadSignaling sharedObj = null;
private final Scanner input = new Scanner(System.in);
public Producer(ThreadSignaling obj) {
this.sharedObj = obj;
}
#Override
public void run() {
int value = -1;
System.out.println("Press Ctrl-c to stop... ");
while (true) {
System.out.println("Enter any integer value : ");
if (input.hasNextInt()) {
value = input.nextInt();
} else {
this.sharedObj.finish();
return;
}
this.sharedObj.put(value);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException while sleeping" + e);
}
}
}
}
public class Consumer implements Runnable {
private ThreadSignaling sharedObj = null;
public Consumer(ThreadSignaling obj) {
this.sharedObj = obj;
}
#Override
public void run() {
while (true) {
this.sharedObj.get();
}
}
}
public class MainThread {
public static void main(String[] args) {
ThreadSignaling sharedObj = new ThreadSignaling();
Producer in = new Producer(sharedObj);
Consumer out = new Consumer(sharedObj);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
} enter code here
The problem with your code is that you do not have an exit condition for the Consumer. The run() method of the Consumer will run forever, and while doing repeated get calls on the shared object.
What you need to do is to make aware the Consumer that the Producer has set the stopFlag in the shared object. And if that stopFlag is true then the loop in the Consumer should also finish. There are several ways you can do that:
redefine get method to return the value of stopFlag;
define a new method to return just the value of stopFlag;
In either cases, make a test in the Consumer.run() and if the value is true, just do a return so the infinite loop ends.
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) {
}
}
}