Use of Notify Method in Multithreading - java

I am learning multithreading.
I tried to implement producer consumer problem in Java.Its working fine.
But if i remove notify call the program goes into a deadlock state.Why?
Its going on deadlock when size of queue becomes 0.Ideally when size becomes 0,wait should be called inside consumer and producer should started working.
import java.io.*;
import java.util.*;
class Consumer implements Runnable{
Queue<Integer> q;
int n;
public void run() {
while(true){
synchronized (q) {
while(q.size()==0){
try {
System.out.println("q.size="+q.size());
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("item consumed="+q.poll());
q.notify();
try {
Thread.sleep((int)(Math.random() * 100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Consumer(Queue<Integer> queue,int n){
q=queue;
this.n=n;
}
}
class Producer implements Runnable{
Queue<Integer> q;
int n;
public void run() {
int x=1;
while(true){
synchronized (q) {
while(q.size()==n){
try {
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("item produced="+x+" q.size="+q.size());
q.add(x++);
q.notify();
try {
Thread.sleep((int)(Math.random() * 100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Producer(Queue<Integer> queue,int n){
q=queue;
this.n=n;
}
}
public class App
{
public static void main( String[] args ) throws InterruptedException
{
int n=100;
Queue<Integer> q=new LinkedList<Integer>();
Thread t1=new Thread(new Producer(q, n));
Thread t2=new Thread(new Consumer(q, n));
t1.start();
t2.start();
t1.join();
t2.join();
}
}

you required notify because when one thread is on wait state because queue is empty or full come to running state if some other thread notify after putting if queue is empty and taking queue is full.
put q.wait(10); so your code will not go on deadlock because after time it will check while loop condition.
It is always best practice to use notify in above usecase

Related

A question about Producer-Consumer Model in Java

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();
}
}
}
}

Synchronized Block locked on class [duplicate]

This question already has an answer here:
Why Java throw java.lang.IllegalMonitorStateException when I invoke wait() in static way synchronized block?
(1 answer)
Closed 2 years ago.
In the below code for producer and consumer, I thought that the produce() and consume() methods are synchronized on Class Lock (Processor.class), but i am getting an exception stating IllegalMonitorStateException, which occurs for objects on which we don't acquire lock but we notify on that objects.
Can anyone tell me where i have gone wrong in the program.
package ProducerConsumer;
public class Main {
public static void main(String[] args) {
Processor processor = new Processor();
Thread producer = new Thread(new Runnable() {
public void run() {
try {
processor.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread consumer = new Thread(new Runnable() {
public void run() {
try {
processor.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("\t\t\tStarting both producer and consumer Threads.");
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\t\t\tEnding all the Threads.");
}
}
import java.util.List;
import java.util.ArrayList;
public class Processor {
private List<Integer> list = new ArrayList<>();
private int value = 0;
private final int LIMIT = 5;
public void produce() throws InterruptedException
{
synchronized(Processor.class){
while(true)
{
if(list.size() == LIMIT){
System.out.println("Waiting for consumer to consume resources");
wait();
}
else{
value++;
System.out.println("The produced resource is : "+value);
list.add(value);
notify();
}
}
}
}
public void consume() throws InterruptedException
{
synchronized(Processor.class){
while(true)
{
if(list.isEmpty()){
System.out.println("Waiting for producer to produce the resources");
wait();
}
else{
System.out.println("The consumer Consumed Resource is : "+list.remove(0));
notify();
}
}
}
}
}
Your wait() & notify() are invoked on this i.e. Processor processor = new Processor(); but your are locking/synchronizing on Processor.class object. You can fix your code to work as below.
class Processor {
private List<Integer> list = new ArrayList<>();
private int value = 0;
private final int LIMIT = 5;
public void produce() throws InterruptedException
{
synchronized(Processor.class){
while(true)
{
if(list.size() == LIMIT){
System.out.println("Waiting for consumer to consume resources");
Processor.class.wait();
}
else{
value++;
System.out.println("The produced resource is : "+value);
list.add(value);
Processor.class.notify();
}
}
}
}
public void consume() throws InterruptedException
{
synchronized(Processor.class){
while(true)
{
if(list.isEmpty()){
System.out.println("Waiting for producer to produce the resources");
Processor.class.wait();
}
else{
System.out.println("The consumer Consumed Resource is : "+list.remove(0));
Processor.class.notifyAll();
}
}
}
}
}

How to write guaranteed deadlock via wait/notify

I visited interview some recently. Interviewer asked me to write guaranteed deadlock.
I have wrote following:
public class DeadLockThreadSleep {
private static class MyThread implements Runnable {
private Object o1;
private Object o2;
#Override
public void run() {
try {
test(o1, o2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public MyThread(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
public void test(Object o1, Object o2) throws InterruptedException {
synchronized (o1) {
System.out.println("1.acquired: " + o1);
Thread.sleep(1000);
synchronized (o2) {
System.out.println("2.acquired: " + o2);
}
}
}
}
public static void main(String[] args) {
Object o1 = new Object();
Object o2 = new Object();
new Thread(new MyThread(o1, o2)).start();
new Thread(new MyThread(o2, o1)).start();
}
}
Then he asked if I sure that it is guaranted. I rememebered that Thread.sleep nothing guaranteed.
Then I wrote this code:
public static void main(String[] args) {
final Thread mainThread = Thread.currentThread();
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
mainThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this answer was accepted.
Also he asked to write analog via wait/notify. I thought a lot and I cannot imagine how to write this.
Is it possible?
This may be done by creating a cycle where one thread holds a resource and waits for another resource whereas the other thread does the same but in reverse order.
Thread tholds resourceOne and waits for resourceTwo , whereas t1holds resourceTwo and waits for resourceOne
Below is a sample code:
public class WaitNotifyLock {
boolean isONHold = false;
public synchronized void hold(){
while(isONHold){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
isONHold = true;
System.out.println(Thread.currentThread().getId() + " : Holded");
}
public synchronized void unHold(){
while(!isONHold){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getId() + " : Produced");
isONHold = false;
notify();
}
public static void main(String[] args) {
WaitNotifyLock resourceOne = new WaitNotifyLock();
WaitNotifyLock resourceTwo = new WaitNotifyLock();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
resourceOne.hold();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
resourceTwo.hold();
resourceOne.unHold();
resourceTwo.unHold();
}
});
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
resourceTwo.hold();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
resourceOne.hold();
resourceTwo.unHold();
resourceOne.unHold();
}
});
t.start();
t1.start();
}
}
A deadlock is a so-called liveness hazard (others are starvation, poor responsiveness, or livelocks), where two main types can be considered:
Lock-ordering deadlocks
Resource deadlocks
However, the Java documentation simplifies this as follows:
Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.
Hence, IMHO you could simply enforce a deadlock with this:
public class DeadlockDemo {
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
new Thread(() -> waitLeftNotifyRight(a, b)).start();
waitLeftNotifyRight(b, a);
}
public static void waitLeftNotifyRight(Object left, Object right) {
synchronized (left) {
try {
System.out.println("Wait");
left.wait();
} catch (InterruptedException e) { /* NOP */ }
}
synchronized (right) {
System.out.println("Notify");
right.notify();
}
}
}
This demo never terminates because the created thread waits on a's monitor, whereas the main thread waits on b's monitor. As a result, the corresponding notify() methods aren't invoked (which would terminate the program).

Threads running at same time instance

I have a requirement threading where I need to initiate a thread which will run continuously doing some DB operations . A second thread will be present which needs to run for every 30 secs. The job of the second thread will be killing the first thread and start a new instance of the first thread.
I tried several ways to achieve this but I am not able to do the same.
public class ThreadMain {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
final CyclicBarrier gate = new CyclicBarrier(3);
Thread t1 = new Thread(){
public void run(){
try {
gate.await();
while(true)
{
System.out.println("Thread1");
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
Thread t2 = new Thread(){
public void run(){
try {
gate.await();
while(true)
{
System.out.println("Continiously running thread:-Thread2");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
t1.start();
t2.start();
This seems to work nicely:
// Thread that runs forever.
volatile static Thread forEverThread = null;
static class ForEver implements Runnable {
#Override
public void run() {
try {
while (true) {
Thread.sleep(1000);
System.out.println("For Ever!");
}
} catch (InterruptedException ex) {
// Just quit if I was interrupted.
}
}
}
// Stop the thread if it is running.
private static void stopForeverThread() throws InterruptedException {
// Skip if non-existent.
if (forEverThread != null) {
// Make sure no-one else is already doing it.
synchronized (forEverThread) {
// Still not null?
if (forEverThread != null) {
// Interrupt it.
forEverThread.interrupt();
// Wait for it to finish.
forEverThread.join();
// Clear it.
forEverThread = null;
}
}
}
}
private static void restartForeverThread() throws InterruptedException {
System.out.println("Restarting...");
// Stop it if it is running.
stopForeverThread();
// Start it again.
forEverThread = new Thread(new ForEver());
forEverThread.start();
System.out.println("Restarted");
}
public static void start() throws InterruptedException {
// Start it all up.
restartForeverThread();
// Timed event to restart it.
Timer restartTimer = new Timer(true);
restartTimer.scheduleAtFixedRate(
new TimerTask() {
#Override
public void run() {
try {
// Restart every few seconds.
restartForeverThread();
} catch (InterruptedException ex) {
// We were interrupted during restart - Log it.
}
}
// Every few seconds.
}, 0, 10 * 1000);
}
public static void main(String args[]) {
try {
// Start it all up.
start();
// Hang around for a while - to see what happens.
Thread.sleep(60 * 1000);
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
If your database task is interruptible (i.e. it reacts on thread interruption and hence can be cancelled by that), the best strategy is to use an ScheduledExecutorService for both, the database task itself and the restart task that runs periodically.
Note that task and thread are two different things: While a task is a piece of work that should be run, threads are the mechanism to do this in parallel.
static class DatabaseTask implements Runnable {
public void run() {
...
}
}
static class RestartTask implements Runnable {
private final ExecutorService executor;
private volatile Future<Void> future;
public RestartTask(ExecutorService executor) {
this.executor = executor;
}
public void run() {
if (future != null) {
future.cancel(true);
}
future = executor.submit(new DatabaseTask());
}
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new RestartTask(executor), 0, 30, TimeUnit.SECONDS);
Note that if your DatabaseTask is NOT sensitive to thread interruption and continues to perform database operations, the number of threads executing database tasks will grow continously - probably not what you want. So make sure, all blocking database operations are either interruptible, or terminate within a reasonable amount of time.

Print Natural Sequence with help of 2 threads(1 is printing even and 2'nd is printing odd)

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) {
}
}
}

Categories