public class Main2 {
public static void main(String[] args) {
new Test2().start();
new Test2().start();
}
}
class Test2 extends Thread {
#Override
synchronized public void run() {
try {
System.out.println("begin wait");
wait();
} catch (Exception ex) {
}
}
}
As the actual result of running the test:
begin wait,
begin wait,
two times from the two threads.
Contrast to the expected result:
begin wait,
only one time from one of the two threads because wait() is called inside the synchronized run() method.
Why could call to Object's wait() break thread synchronization?
Thans a lot!
public class Main3 {
public static void main(String[] args) {
Test3 t = new Test3();
new Thread(t).start();
new Thread(t).start();
}
}
class Test3 implements Runnable {
synchronized public void run() {
try {
System.out.println("begin wait");
wait();
} catch (Exception ex) {
}
}
}
#akf & #Sean Owen
Thanks for your replies. Sorry for my mistake, now i modified the code to place the synchronization on the same object's run(), the result remained: begin wait, begin wait, two times.
#akf
wait will release the lock that
synchronize has grabbed, and will be
re-gotten once the thread is notified.
Could you elaborate a little bit?
The object that you are synchronizing on in this example is not the class, but the instance, so each new Test2 object would be synchronizing on a different monitor.
The method you might be looking for here is sleep, not wait. wait will release the lock that synchronized has grabbed, and will be re-gotten once the thread is notified.
Note that for your test to work correctly, you will need to lock on a common object. If you want to see wait in action, I have thrown together a simple app that will pop up a frame with a "Notify" button. Two threads will be started that wait on a common object and are in turn notified when the button is pressed.
public static void main(String[] args)
{
final Object lock = new Object();
final JFrame frame = new JFrame("Notify Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Notify");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
synchronized(lock) {
lock.notify();
}
}
});
frame.add(button);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible( true );
}
});
new Thread(new Runnable() {
public void run() {
synchronized(lock) {
try {
System.out.println("1. starting");
lock.wait();
System.out.println("1. step 1");
lock.wait();
System.out.println("1. step 2");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
synchronized(lock) {
try {
System.out.println("2. starting");
lock.wait();
System.out.println("2. step 1");
lock.wait();
System.out.println("2. step 2");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}).start();
}
For a simple explanation of wait, the JavaDoc is always a good place to start:
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
You have two different Test2 objects. Synchronized methods lock on the object. They are not acquiring the same lock, so no it should print twice.
an simple example that can help you is this:
public class test {
public static void main(String[] args) {
Prova a=new Prova();
new Test2(a).start();
new Test2(a).start();
}
}
class Prova{
private boolean condition;
public void f(){
while(condition){
//Thread.currentThread Returns a reference to the currently executing thread object.
//Thread.getName() return name Thread
System.out.println(Thread.currentThread().getName()+" begin wait");
try{
wait();
}catch(InterruptedException c){return;}
}
System.out.println(Thread.currentThread().getName()+" first to take the mutex");
condition=true;
}
}
class Test2 extends Thread {
private Prova a;
private static boolean condition;
public Test2(Prova a){
this.a=a;
}
#Override
public void run() {
synchronized(a){
try {
a.f();
} catch (Exception ex) {
}
}
}
}
in this case the two threads synchronize an object, the first taking the lock release message, the second one waits. in this example uses the condition variable
summary to wait/notify mechanism:
1)current thread reaches one object's synchronized code block which contains the call to wait(), it competes with other threads for the lock(the object's monitor), as winner it executes the block till the call to wait() encounters.
2)by calling wait(), current thread releases the lock to other competing threads, then halts execution, wait for notify being sent from another thread who succeeds in obtaining the lock.
JavaDoc:
A thread becomes the owner of
the object's monitor in one of three
ways:
•By executing a synchronized instance
method of that object.
•By executing
the body of a synchronized statement
that synchronizes on the object.
•For
objects of type Class, by executing a
synchronized static method of that
class.
3)another thread reaches the same object's yet another synchronized code block which contains the call to notify/notifyAll(), it competes with other threads for the lock, as winner it executes the block till finishing the call to notify/notifyAll(). It will release the lock either by call to wait() or at the end of the execution on the block.
4)upon receiving notify/notifyAll(), current thread competes for the lock, as winner the execution continues where it has halted.
simple example:
public class Main3 {
public static void main(String[] args) {
Test3 t = new Test3();
new Thread(t).start();
new Thread(t).start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
t.testNotifyAll();
}
}
class Test3 implements Runnable {
synchronized public void run() {
System.out.println(Thread.currentThread().getName() + ": " + "wait block got the lock");
try {
wait();
} catch (Exception ex) {
}
System.out.println(Thread.currentThread().getName() + ": " + "wait block got the lock again");
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
System.out.println(Thread.currentThread().getName() + ": " + "bye wait block");
}
synchronized void testNotifyAll() {
System.out.println(Thread.currentThread().getName() + ": " + "notify block got the lock");
notifyAll();
System.out.println(Thread.currentThread().getName() + ": " + "notify sent");
try {
Thread.sleep(2000);
} catch (Exception ex) {
}
System.out.println(Thread.currentThread().getName() + ": " + "bye notify block");
}
}
output:
Thread-0(or 1): wait block got the
lock
Thread-1(or 0): wait block got
the lock
main: notify block got the
lock
main: notify sent
main: bye notify block
Thread-0(or 1): wait block
got the lock again
Thread-0(or 1): bye
wait block
Thread-1(or 0): wait block
got the lock again
Thread-1(or 0): bye
wait block
Related
public class MyVisibility {
private static int count = 0;
private static Object lock = new Object();
public static void main(String[] args) {
new MyVisibility.thread1().start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
new MyVisibility.thread2().start();
}
static class thread1 extends Thread {
int i = 0;
#Override
public void run() {
super.run();
while (true) {
synchronized (lock) {
count++;
System.out.println("Thread one count is " + count);
try {
lock.wait();
System.out.println("i am notified");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count > 5) {
return;
}
}
}
}
static class thread2 extends Thread {
int i = 10;
#Override
public void run() {
super.run();
while (true) {
synchronized (lock) {
count++;
System.out.println("Thead 2 count is " + count);
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count > 10) {
return;
}
}
}
}
}
In above code,
Current result on execution : I can see lock.notify() is getting called only after end of the while loop.
My assumption is Since lock.notify() is getting called immediately after count variable getting incremented, and immediately it should notify the waiting thread to resume its execution, instead after second thread completion of execution call is going for waiting thread to resume, what is the reason for this, can someone correct me what was wrong with my understanding.
Thank you.
Your deduction - "I can see lock.notify() is getting called only after end of the while loop" is not entirely correct. Try running multiple times, or put break point just after synchronized block of thread2, and then you will see thread1 "i am notified" being printed.
From documentation of notify() -
The awakened thread will not be able to proceed until the current
thread relinquishes the lock on this object
In your case before thread2 relinquishes lock and then thread1 acquires lock, thread2 acquires lock again by going into synchronized block.
I am new to Java multithreading. I created simple producer-consumer pattern using wait and notify but my producer is getting called only once in tbe starting.
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorldp = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
}
}
}
}
I am creating separate threads for producer and consumer. Producer thread only gets called in the starting and then after it is never getting executed.
I tried two option to overcome this issue. first I put while condition outside of synchronized block second is given below.
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
notify();
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
wait();
}
}
}
}
Both works great. Which one the of the appropriate solution to use ? I am still unable to figure out why the code I put in question is not working properly.
I am still unable to figure out why the code I put in question is not working properly
The wait() in producer() releases the monitor which allows consumer() to enter its synchronized block. Then the wait() in producer() starts waiting till consumer() calls notify() and releases the monitor (i.e. exits its synchronized block). You never exit synchronized in consumer() therefore the wait() in producer() is blocked forever
I am still unable to figure out why the code I put in question is not
working properly
I've managed to fix your code, and I've attached below the fixed code snippet.
I've introduced a boolean instance variable named isConsumed for the ProducerConsumerWorld. In doing so, what essentially happens is that after Producer Thread produces, he updates the state of isConsumed to false, since he has produced something which is yet to be consumed. Afterwards, the producer notifies the the Consumer thread, that Producer has finished producing. Next, it invokes wait() on the ProducerConsumerWorld which releases Producer's lock on ProducerConsumerWorld. Then, it waits for the lock on ProducerConsumerWorld.
Meanwhile, the Consumer Thead acquires the lock on ProducerConsumerWorld, which allows it to enter the consumer method, where it checks if there is produce yet to be consumed. If so, it consumes and updates the isConsumed variable to true, and notifies the produce has been consumed. Then the consumer proceeds to releases its lock on ProducerConsumerWorld by calling wait(), and waits to reacquire the lock on ProducerConsumerWorld after Producer has consumed.
Note:
Calling notify() doesn't release a lock until the thread moves out of the synchronized block, or wait() is called, thus releasing the lock.
Source: Oracle's OCA/OCP Java SE 7 Study Guide Page 760
Code:
import java.util.Scanner;
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorld p = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class ProducerConsumerWorld{
boolean consumed = false;
public void producer() throws InterruptedException{
System.out.println("Producer thread started running");
synchronized (this) {
while(this.consumed == true){ // Consumer has consumed and is waiting for produce
System.out.println("Resumed Producing");
this.consumed = false;
notify();
wait();
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(this.consumed == false){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
this.consumed = true;
System.out.println("consumed all");
notify();
wait();
}
}
}
}
This gives me an output like,
According to How to use wait and notify in Java? I have to synchronized on the same object to call notify.
I have synchronized on the same haveCoffee object. Why I am getting IllegalMonitorStateException when I call the notify method ?
I am Sleeping
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.example.concurrent.basic.WaitAndNotify$2.run(WaitAndNotify.java:42)
in the following code:
public class WaitAndNotify {
public static void main(String[] args) {
Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};
Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}
On the first Thread, you call wait on an object while having its monitor (the object being this haveCoffee).
However, on the second thread, you call notify() on me, while having the monitor of haveCoffee.
This should work:
public class WaitAndNotify {
public static void main(String[] args) {
final Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};
Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}
From oracle documentation page,
public class IllegalMonitorStateException
extends RuntimeException
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
Whenever you get this exception, just go through your code and check wait() and notify() calls and the object on which these calls have been invoked. You can easily figure out what went wrong.
EDIT:
wait() or notify() calls have to be invoked on object once you get monitor on that object.
You should be calling
haveCoffee.notify()
instead of just
notify().
If you invoke just notify() it calls the notify() method on the this object which is the second thread me where as you have synchronized on haveCoffee thread and that is the reason for exception you are seeing.
So the code in thread2 me should looks like:
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I am learning threading in java. As per the description of finally block in an Oracle tutorial:
Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
So I tried to interrupt a thread in try catch block and check whether finally is executed in following class. But as per the output of the program, finally block is executed. Can someone explain what happened?
package com.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock{
public static void main(String[] args) throws InterruptedException {
MyThread lockT= new MyThread();
Thread t= new Thread(lockT);
t.setName("TempThread1");
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
class MyThread implements Runnable {
Lock lock;
public MyThread() {
lock= new ReentrantLock();
}
#Override
public void run() {
try {
if(lock.tryLock()){
Thread.sleep(5000);
while (!Thread.currentThread().isInterrupted()) {
System.out.println("My thread name is "+ Thread.currentThread().getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println("finally ");
lock.unlock();
}
}
}
The rule here is saying: may not execute which does not mean it will not execute.
So basically the rule is saying: don't rely that the finally block will be executed, we don't provide such guarantees.
I know it's a old thread but I'd like to present a situation where the threads get interrupted and doesn't execute finally: Here is the sample code:
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.LockWork();
}public void LockWork() {
WithLock withLock = new WithLock();
Thread t1 = new Thread(() -> {
withLock.produce();
});
Thread t2 = new Thread(() -> {
withLock.consume();
});
ExecutorService service= Executors.newCachedThreadPool(new WithLockThreadFactory());
Future f1=service.submit(t1);
Future f2=service.submit(t2);
//f1.cancel(true);
try {
System.out.println("-------------------------------------sleeping now-------------------------------------");
Thread.sleep(3000);
System.out.println("-------------------------------------Intereputing Producer-------------------------------------");
f1.cancel(true);
service.shutdown();
Thread.sleep(1000);
System.out.println("is Producer done: "+f1.isDone());
service.awaitTermination(1, TimeUnit.DAYS);
System.out.println("is Consumer done: "+f2.isDone());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Ending Program");
}
now There is my Thread Factory:
public class WithLockThreadFactory implements ThreadFactory {
private int counter;
public WithLockThreadFactory() {
this.counter = 1;
}
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "WithLockThreadFactoryThread " + counter);
counter++;
return t;
}
now WithLock Class:
public class WithLock {
ReentrantLock lock = new ReentrantLock(true);
LinkedList<Integer> linkedList = new LinkedList<>();
Condition isEmpty = lock.newCondition();
Condition isFull = lock.newCondition();
int limit = 10;
volatile int interruptCounter = 0;
public void produce() {
System.out.println("WithLock.produce() Name: " + Thread.currentThread().getName());
try {
int value = 1;
while (true) {
lock.lockInterruptibly();
if (limit == linkedList.size()) {
System.out.println("acquiring lock in produce");
isEmpty.await(3000, TimeUnit.MILLISECONDS);
}
linkedList.add(value % limit);
System.out.println("value added to list: " + value % limit);
value++;
isFull.signal();
System.out.println("notifiedy lock in produce");
lock.unlock();
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("I was interupted Producer");
interruptCounter++;
System.out.println("interruptCounter value :" + interruptCounter);
} finally {
lock.unlock();
System.out.println("Finally Unlocked Producuer");
}
System.out.println("Ending things now: Producer");
}
public void consume() {
System.out.println("WithLock.consume() Name: " + Thread.currentThread().getName());
try {
while (true) {
lock.lockInterruptibly();
// no use as poll doesn't throw an exception if the queue is
// empty
if (linkedList.size() == 0) {
System.out.println("acquiring lock in consume");
isFull.await(3000, TimeUnit.MILLISECONDS);
if (interruptCounter > 2) {
break;
}
}
System.out.println("removing element from queue: " + linkedList.poll());
isEmpty.signal();
System.out.println("notifiedy lock in consume");
lock.unlock();
Thread.sleep(1000);
if (interruptCounter != 0) {
interruptCounter++;
}
}
} catch (InterruptedException e) {
System.out.println("I was Interupted Consumer");
} finally {
lock.unlock();
System.out.println("Finally Unlocked Consumer");
}
System.out.println("Ending things now: Consume");
}
}
and this is the output in the console:
-------------------------------------sleeping now-------------------------------------
WithLock.produce() Name: WithLockThreadFactoryThread 1
WithLock.consume() Name: WithLockThreadFactoryThread 2
value added to list: 1
notifiedy lock in produce
removing element from queue: 1
notifiedy lock in consume
acquiring lock in consume
value added to list: 2
notifiedy lock in produce
removing element from queue: 2
notifiedy lock in consume
acquiring lock in consume
value added to list: 3
notifiedy lock in produce
removing element from queue: 3
notifiedy lock in consume
-------------------------------------Intereputing Producer-------------------------------------
I was interupted Producer
interruptCounter value :1
acquiring lock in consume
is Producer done: true
removing element from queue: null
notifiedy lock in consume
acquiring lock in consume
Finally Unlocked Consumer
Ending things now: Consume
is Consumer done: true
Ending Program
This is something I found interesting and wanted to share. I tried it in JAVA8.
If the JVM exits...
Try System.exit() call...
First and foremost, Oracle's tutorials are descriptive and not normative. Your quote should by no means be taken as specification of behavior.
The thread can be interrupted while executing the finally block, in which case the said finally block may indeed fail to complete. This is, however, fully under your control and you can always write such a finally which is not susceptible to this happening.
Rest assured that the finally block will not be skipped over due to a regular InterruptedException occurring within its try block.
If a thread is being repeatedly stop()ped, however, it will be harder to ensure the finally block executes.
I am trying to understand the use of Synchronized block.
In the below program, Inside a produce and consumer method I have created a synchronized block and if I lock it by using lock1(object). I am getting the following error, why is this, why am i getting this error?
I am aware that by replacing lock1 by this(same class). I can get rid of the error. I still want to know why this error as everything seems very logical to me.
Program
import java.util.Scanner;
public class Worker {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void produce() throws InterruptedException {
synchronized (lock1) {
System.out.println("Producer thread running");
wait();
System.out.println("Producer resumed");
}
}
public void consumer() throws InterruptedException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(2000);
synchronized (lock1) {
System.out.println("Waiting for return key");
scanner.nextLine();
System.out.println("return key is pressed");
notify();
Thread.sleep(5000);
System.out.println("Consumer is over");
}
}
public void main() {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at Worker.produce(Worker.java:14)
at Worker$1.run(Worker.java:43)
at java.lang.Thread.run(Unknown Source)
synchronized (lock1) {
System.out.println("Producer thread running");
wait();
System.out.println("Producer resumed");
}
You acquire the monitor of lock1 and then proceed to wait on this which fails because, as the documentation of Object#wait states,
The current thread must own this object's monitor.
You need to call lock1.wait() and lock1.notify(). You can only call wait() or notify() on an object on which you hold the lock (lock1 in this case).
In the synchronized block the current thread is the owner of the synchronization object's monitor.
In your case it is lock1.
According to the javadoc of Object.wait()
The current thread must own this object's monitor.
and Object.notify()
This method should only be called by a thread that is the owner of this object's monitor.
you must change your code to
synchronized (lock1) {
System.out.println("Producer thread running");
lock1.wait();
System.out.println("Producer resumed");
}
and
synchronized (lock1) {
System.out.println("Waiting for return key");
scanner.nextLine();
System.out.println("return key is pressed");
lock1.notify();
Thread.sleep(5000);
System.out.println("Consumer is over");
}
To call wait() and notify() you need to own the object's monitor you want to call these two methods.
Link to javadoc Object.wait()
Citation from above link:
The current thread must own this object's monitor.
I am showing how I fixed the producer-consumer problem.
I have using different way then you. I think this will help you..
And the to make any block or method synchronized their are some condition :
synchronized methods prevent more than one thread from accessing an
object's critical method code simultaneously.
You can use the synchronized keyword as a method modifier, or to start a
synchronized block of code.
To synchronize a block of code (in other words, a scope smaller than the
whole method), you must specify an argument that is the object whose lock
you want to synchronize on.
While only one thread can be accessing synchronized code of a particular
instance, multiple threads can still access the same object's unsynchronized code.
static methods can be synchronized, using the lock from the
java.lang.Class instance representing that class.
All three methods—wait(), notify(), and notifyAll()—must be
called from within a synchronized context! A thread invokes wait() or
notify() on a particular object, and the thread must currently hold the lock
on that object.
class P implements Runnable{
Data d;
P(Data d){
this.d = d;
new Thread(this,"Producer").start();
}
public void run(){
for(int i=0; i<=20; i++){
d.set(i);
System.out.println("put -> "+i);
}
}
}
class C implements Runnable{
Data d;
C(Data d){
this.d = d;
new Thread(this,"Consumer").start();
}
public void run(){
for(int i=0; i<=20; i++){
int n = d.get();
System.out.println("get -> "+n);
}
}
}
class Data{
int n;
boolean valueset=false;
synchronized void set(int n){
if(valueset){
try{
wait();
}catch(Exception e){
System.out.println("set -> Exception "+e);
}
}
this.n = n ;
valueset=true;
notify();
}
synchronized int get(){
if(!valueset){
try{
wait();
}catch(Exception e){
System.out.println("get -> Exception "+e);
}
}
valueset=false;
notify();
return n ;
}
}
class PC{
public static void main(String[] args){
Data d = new Data();
new P(d);
new C(d);
}
}
You can download solution of producer consumer from here :
https://www.mediafire.com/?52sa1k26udpxveu