Selasa, 26 Agustus 2014

Inter Thread Communication in Java using Wait Notify Example



Wait and notify methods in Java are used for inter-thread communication i.e. if one thread wants to tell something to another thread, it uses notify() and notifyAll() method of java.lang.Object. Classical example of wait and notify method is Producer Consumer design pattern, where One thread produce and put something on shared bucket, and then tell other thread that there is an item for your interest in shared object, consumer thread than pick than item and do his job, without wait() and notify(), consumer thread needs to be busy checking, even if there is no change in state of shared object. This brings an interesting point on using wait and notify mechanism, a call to notify() happens, when thread changed state of shared object i.e. in this case producer change bucket from empty to not empty, and consumer change state from non empty to empty. Also wait and notify method must be called from synchronized context, wondering why, read this link for some reasons which makes sense. Another important thing to keep in mind while calling them is, using loop to check conditions instead of if block. This is really tricky for beginners, which often don't understand difference and wonders why wait and notify get called form loops. Joshua Bloch has a very informative item on his book Effective Java, I strongly suggest reading that. In short, a waiting thread may woke up, without any change in it's waiting condition due to spurious wake up. For example, if a consumer thread, which is waiting because shared queue is empty, gets wake up due to a false alarm and try to get something from queue without further checking whether queue is empty or not than unexpected result is possible. Here is standard idiom for calling wait, notify and notifyAll methods in Java :



How to call wait method in Java :







synchronized (object) {


         while
()


             object.wait();


         ... // Perform action appropriate
to condition


 }




and here is complete example of calling wait and notify method in Java using two threads, producer and consumer








Java Inter Thread Communication Example - Wait and Notify


Java inter thread communication example wait notify methodWe have a shared Queue and two threads called Producer and Consumer. Producer thread puts number into shared queue and Consumer thread consumes numbers from shared bucket. Condition is that once an item is produced, consumer thread has to be notified and similarly after consumption producer thread needs to be notified. This inter thread communication is achieved using wait and notify method. Remember wait and notify method is defined in object class, and they are must be called inside synchronized block.





package concurrency;


import java.util.LinkedList;


import java.util.Queue;


import org.apache.log4j.Logger;





public class InterThreadCommunicationExample {





    public static void main(String
args[]) {





        final
Queue sharedQ =
new LinkedList();





        Thread producer = new
Producer(sharedQ);


        Thread consumer = new
Consumer(sharedQ);





        producer.start();


        consumer.start();





    }


}





public class Producer extends Thread {


    private static final Logger logger
= Logger.
getLogger(Producer.class);


    private final
Queue sharedQ;





    public Producer(Queue
sharedQ) {


        super("Producer");


        this.sharedQ = sharedQ;


    }





    @Override


    public void run() {





        for (int i = 0; i < 4; i++) {





            synchronized (sharedQ) {


                //waiting condition - wait
until Queue is not empty


                while (sharedQ.size() >= 1) {


                    try {


                        logger.debug("Queue is full, waiting");


                        sharedQ.wait();


                    } catch
(InterruptedException ex) {


                        ex.printStackTrace();


                    }


                }


                logger.debug("producing : " + i);


                sharedQ.add(i);


                sharedQ.notify();


            }


        }


    }


}





public class Consumer extends Thread {


    private static final Logger logger
= Logger.
getLogger(Consumer.class);


    private final
Queue sharedQ;





    public Consumer(Queue
sharedQ) {


        super("Consumer");


        this.sharedQ = sharedQ;


    }





    @Override


    public void run() {


        while(true) {





            synchronized (sharedQ) {


                //waiting condition - wait
until Queue is not empty


                while (sharedQ.size() == 0) {


                    try {


                        logger.debug("Queue is empty, waiting");


                        sharedQ.wait();


                    } catch
(InterruptedException ex) {


                        ex.printStackTrace();


                    }


                }


                int number =
sharedQ.
poll();


                logger.debug("consuming : " + number );


                sharedQ.notify();


              


                //termination condition


                if(number == 3){break; }


            }


        }


    }


}





Output:


05:41:57,244 0    [Producer] DEBUG concurrency.Producer  - producing : 0


05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - Queue is full, waiting


05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - consuming : 0


05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - Queue is empty, waiting


05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - producing : 1


05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - Queue is full, waiting


05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - consuming : 1


05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - Queue is empty, waiting


05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - producing : 2


05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - Queue is full, waiting


05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - consuming : 2


05:41:57,260 16   [Consumer] DEBUG concurrency.Consumer  - Queue is empty, waiting


05:41:57,260 16   [Producer] DEBUG concurrency.Producer  - producing : 3


05:41:57,276 32   [Consumer] DEBUG concurrency.Consumer  - consuming : 3




That's all on this simple example of Inter thread communication in Java using wait and notify method. You can see that both Producer and Consumer threads are communicating with each other and sharing data using shared Queue, Producer notifies consumer when there is an item ready for consumption and Consumer thread tells Producer once it's done with consuming. This is classical example of Producer Consumer design pattern as well, which inherently involves inter-thread communication and data sharing between threads in Java.



























Source:http://javarevisited.blogspot.com/2013/12/inter-thread-communication-in-java-wait-notify-example.html

Tidak ada komentar:

Posting Komentar