Pages

Label

Tampilkan postingan dengan label multi threading. Tampilkan semua postingan
Tampilkan postingan dengan label multi threading. Tampilkan semua postingan

Rabu, 30 Januari 2019

wait(), notify() and notifyAll() in Java



Hello Guys !!! Hope You all are doing well.
Today I am going to discuss one of the most import concept of java Thread.
wait(), notify() and notifyAll() methods are quite obvious because they are the one of the three methods of total 9 methods from java.lang.Object. I am sharing here some practical tips and points about wait(), notify() and notifyAll() in Java and its uses in java program.

1. wait, notify and notifyAll are related to threads they are not defined in java.lang.Thread class, instead they are defined in the Object class. why? as per my understanding there are three reason :-


(A) Wait and notify is not just normal methods or synchronization utility,They are communication mechanism between two threads in Java. So An Object class is correct place to make them available for every object.

(B) Locks are made available as per Object basis, that's why wait and notify is declared in Object class rather then Thread class.

(C) As per Java design, the thread can not be specified, it is always the current thread running the code. However, we can specify the monitor (object). So it is a good design, if we could make any other thread to wait on a desired monitor.

2. We must call the wait(), notify() and notifyAll() methods from a synchronized context in Java i.e. inside synchronized method or a synchronized block.
why is this restriction??? Explanation:-

(A) The thread must hold the lock on the object it is going to call the wait() or notify() method and that is acquired when it enter into a synchronized context.
If you call it without holding a lock then they will throw IllegalMonitorStateException in Java.

(B) To avoid any potential race condition between wait() and notify() method.

3. The best approach to call wait() method from inside a loop, don't call with an if block because a thread can occasionally or irregularly awake from the wait state without being notified by another party. So in that case, this could result in a bug.
example :-

synchronized (sharedObject) {

while (condition) {

sharedObject.wait();

}

// do something

}



4. When a thread calls the wait() method in Java, it goes to the wait state by releasing the lock, which is later acquired by the other thread who can notify this thread. Here is a nice diagram of how state transition of a thread happens in Java:
Inline image 1

5. A thread waiting due to wait() method call, then it can wake up either by calling notify() or notifyAll() method on the same object or due to interruption.

6. Difference between notify() and notifyAll() is that in case of notify() only one of the waiting thread gets a notification but in case of notifyAll() all thread get notification.

So far, we learned few basic things for wait, notify and notifyAll (which you probably already knew). Let’s write a small java program.

In this program, we will solve producer consumer problem using wait() and notify() methods.
To keep program simple, we will involve only one producer and one consumer thread.
Other features of the program are :

  1. Producer thread produce a new resource in every 1 second and put it in ‘taskQueue’.
  2. Consumer thread takes 1 seconds to process consumed resource from ‘taskQueue’.
  3. Max capacity of taskQueue is 7 i.e. maximum 7 resources can exist inside ‘taskQueue’ at any given time.
  4. Both threads run infinitely.

You can download source code from my github account

ProducerThread.java file add task in TaskQueue . Below is the full code :- 

packagecom.sks.softsolution.example;

importjava.util.List;

publicclassProducerThread implementsRunnable {

privatefinalList<Integer> taskQueue;
privatefinalintMAX_CAPACITY;
publicProducerThread(List<Integer> sharedQueue, intsize)
{
this.taskQueue= sharedQueue;
this.MAX_CAPACITY= size;
}
@Override
publicvoidrun() {
intcounter= 0;
while(true)
{
try
{
ProduceTask(counter++);
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
}
privatevoidProduceTask(inti) throwsInterruptedException
{
synchronized(taskQueue)
{
while(taskQueue.size() == MAX_CAPACITY)
{
System.out.println("Queue is full "+ Thread.currentThread().getName() + " is waiting , size: "+ taskQueue.size());
taskQueue.wait();//calling wait on taskQueue lock
}
Thread.sleep(1000);
taskQueue.add(i);
System.out.println("Produced: " + i);
taskQueue.notifyAll();
}
}
}


ConsumerThread.java is consuming task produced by Producer.java Below is the full code:-
packagecom.sks.softsolution.example;

importjava.util.List;

publicclassConsumerThread implementsRunnable
{
privatefinalList<Integer> taskQueue;
publicConsumerThread(List<Integer> sharedQueue)
{
this.taskQueue= sharedQueue;
}
@Override
publicvoidrun()
{
while(true)
{
try
{
consumeTask();
} catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
}
privatevoidconsumeTask() throwsInterruptedException
{
synchronized(taskQueue)
{
while(taskQueue.isEmpty())
{
System.out.println("Queue is empty "+ Thread.currentThread().getName() + " is waiting , size: "+ taskQueue.size());
taskQueue.wait();
}
Thread.sleep(1000);
inti= (Integer) taskQueue.remove(0);
System.out.println("Consumed: " + i);
taskQueue.notifyAll();
}
}
}
Now finally we have to start producer and consumer thread
packagecom.sks.softsolution.example;

importjava.util.ArrayList;
importjava.util.List;

publicclassProducerConsumerExampleWithWaitAndNotify {
publicstaticvoidmain(String[] args) {
List<Integer> taskQueue= newArrayList<Integer>();
intMAX_CAPACITY= 7;
Thread tProducer= newThread(newProducerThread(taskQueue, MAX_CAPACITY), "Producer");
Thread tConsumer= newThread(newConsumerThread(taskQueue), "Consumer");
tProducer.start();
tConsumer.start();
}

}
Output of this program 
Queue is empty Consumer is waiting , size: 0
Produced: 0
Produced: 1
Produced: 2
Produced: 3
Produced: 4
Produced: 5
Produced: 6
Queue is full Producer is waiting , size: 7
Consumed: 0
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4
Consumed: 5
Consumed: 6
Queue is empty Consumer is waiting , size: 0
Produced: 7
Produced: 8
Produced: 9
Produced: 10
Produced: 11
Produced: 12
Produced: 13
Queue is full Producer is waiting , size: 7
Consumed: 7
Consumed: 8
Please provide your valuable feedback in comment section. it will help me to do my best.
Happy Coding!!!.....

Sleep, wait, yield and join method in Java Thread

Hello Guys !!! Hope you all are doing well. 
Today I am going to discuss sleep, wait, yield and join method uses in java Thread.
The difference between wait and sleep or the difference between sleep and yield in Java are one of the popular core Java interview questions.
Three methods which can be used to pause a thread in Java is :-
  • wait()
  • sleep() and
  • join()

The key difference between wait() and sleep() :-

  1. wait() is used for inter-thread communication while sleep() is used to pause the current thread for a short duration.
  2. when a thread calls the wait() method, it releases the monitor or lock it was holding on that object, but when a thread calls the sleep() method, it never releases the monitor(even if it is holding).
  3. wait() method in Java should be called from synchronized method or block while there is no such requirement for sleep() method
  4. Thread.sleep() method is a static method and applies on current thread, while wait() is an instance specific method and only got wake up if some other thread calls notify method on same object.
  5. in the case of sleep(), sleeping thread immediately goes to Runnable state after waking up while in the case of wait(), waiting for a thread first acquires the lock and then goes into Runnable state.
  6. wait() method normally use on condition as for example Thread wait until a condition is true while sleep is just to put your thread on sleep for a particular interval.
So based upon your need, if you want to pause a thread for specified duration then use sleep() method and if you want to implement inter-thread communication use wait() method.

Coming back to yield()

  • Yield() method is little different than wait() and sleep().
  • it just releases the CPU hold by Thread to give another thread an opportunity to run.
  • Though it's not guaranteed who will get the CPU.
  • It totally depends upon thread scheduler and it's even possible that the thread which calls the yield() method gets the CPU again. Hence, it's not reliable to depend upon yield() method, it's just on best effort basis.

Differences

sleep() 
  • causes the thread to definitely stop executing for a given amount of time
  • if no other thread or process needs to be run, the CPU will be idle (and probably enter a power saving mode).
yield() 
  • method pauses the currently executing thread temporarily for giving a chance to the remaining waiting threads of the same priority to execute. 
  • If there is no waiting thread or all the waiting threads have a lower priority then the same thread will continue its execution. 
  • The yielded thread when it will get the chance for execution is decided by the thread scheduler whose behavior is vendor dependent.

Now coming to join()

The join() method is used to hold the execution of currently running thread until the specified thread is dead(finished execution).

As for example :- t1 and t2 are two threads , t2.join() is called then t1 enters into wait state until t2 completes execution. Then t1 will into runnable state then our specialist JVM thread scheduler will pick t1 based on criteria.

Why we use join() method?

In normal circumstances we generally have more than one thread, thread scheduler schedules the threads, which does not guarantee the order of execution of threads. So we can use join() to wait for a thread to complete its work.

In simple term let say, We have three thread t1, t2 and t3 and we want to run these thread in sequence, one by one the we can go with join.

Please have a look on my example code. For better understanding.

Note:- As per multi threading concept, It is better to use thread to do our work in parallel fashion. There is no benefit for multi threading in serial fashion.
For wait() method follow my previous blog
Thread Sleep Example

packagecom.sks.softsolution.example1;

publicclassThreadSleepExample implementsRunnable {
@Override
publicvoidrun() {
for(inti= 10; i< 13; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
try{
// thread to sleep for 1000 milliseconds
Thread.sleep(1000);
} catch(Exception e) {
System.out.println(e);
}
}

}

publicstaticvoidmain(String[] args) {
Thread t= newThread(newThreadSleepExample());
// this will call run() function
t.start();

Thread t2= newThread(newThreadSleepExample());
// this will call run() function
t2.start();
}
}
Thread Join Example
packagecom.sks.softsolution.example1;

publicclassJoinExample {
publicstaticvoidmain(String[] args) {
Thread th1= newThread(newMyRunnableClass(), "th1");
Thread th2= newThread(newMyRunnableClass(), "th2");
Thread th3= newThread(newMyRunnableClass(), "th3");
// Start first thread immediately
th1.start();
/* Start second thread(th2) once first thread(th1)
* is dead
*/
try{
th1.join();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
th2.start();
/* Start third thread(th3) once second thread(th2)
* is dead
*/
try{
th2.join();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
th3.start();
// Displaying a message once third thread is dead
try{
th3.join();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("All three threads have finished execution");
}
}
packagecom.sks.softsolution.example1;

publicclassMyRunnableClass implementsRunnable{
@Override
publicvoidrun() {
Thread t= Thread.currentThread();
System.out.println("Thread started: "+t.getName());
try{
Thread.sleep(4000);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("Thread ended: "+t.getName());
}

}

Thread Yield() example

package com.sks.softsolution.example1;

import java.util.ArrayList;
import java.util.List;

public class MyThreadYield {

    public static void main(String[] args) {

        List<ExmpThread> list = new ArrayList<ExmpThread>();

        for (int i = 0; i < 3; i++) {
            ExmpThread et = new ExmpThread(i + 5);
            list.add(et);
            et.start();
        }

        for (ExmpThread et : list) {
            try {
                et.join();
            } catch (InterruptedException ex) {
            }
        }
    }
}
package com.sks.softsolution.example1;

public class ExmpThread extends Thread {

    private int stopCount;

    public ExmpThread(int count) {
        this.stopCount = count;
    }

    public void run() {
        for (int i = 0; i < 50; i++) {
            if (i % stopCount == 0) {
                System.out.println("Stoping thread: " + getName());
                yield();
            }
        }
    }

}
Thanks!!! Happy Coding !!!! Please put your comment.
 
[tutup]