Saturday, 16 May 2015

Wait and Notify in Java

In this example we are using low-level multithreading methods of the Object class that allow you to have one or more threads sleeping, only to be woken up by other threads at the right moment. Extremely useful for avoiding those processor-consuming polling loops.


In our example when we are using two producer thread and one consumer thread. After reading new line consumer is sending notify signal for waiting threads. It is up to JVM which thread to resume. If want to resume all threads then we need to call notifyAll method. One more important point is here whenever we call wait, notify or notifyAll method we need have lock on that object. See the second program where after calling notify also threads are not resumed. 

Program 1
//****************************************************************
//* Copyright (c) 2015 . All Rights Reserved.
//****************************************************************
package com.thread.waitnotify;

import java.util.Scanner;

public class Processor {
    public void produce() throws InterruptedException {
        synchronized (this) {
            System.out.println("Producer thread running ....");
            wait();
            System.out.println("Resumed." + Thread.currentThread().getName());
        }
    }

    public void consume() throws InterruptedException {

        final Scanner scanner = new Scanner(System.in);
        Thread.sleep(2000);

        synchronized (this) {
            System.out.println("Waiting for return key.");
            scanner.nextLine();
            System.out.println("Return key pressed.");
            notify();
            Thread.sleep(5000);
        }
    }

    public static void main(final String[] args) throws InterruptedException {

        final Processor processor = new Processor();

        final Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Producer 1");
        final Thread t3 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Producer 2");
        final Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.consume();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer");

        t1.start();
        t2.start();
        t3.start();
    }
}

Output: 

Producer thread running ....
Producer thread running ....
Waiting for return key.


Return key pressed.

Resumed.Producer 1

Note: To resume both threads we need to call notifyAll in consumer.


Program 2

//****************************************************************
//* Copyright (c) 2015 Ford Motor Company. All Rights Reserved.
//****************************************************************
package com.thread.waitnotify;

import java.util.Scanner;

public class Processor {

    Object lock1 = new Object();
    Object lock2 = new Object();

    public void produce() throws InterruptedException {
        synchronized (lock1) {
            System.out.println("Producer thread running ....");
            lock1.wait();
            System.out.println("Resumed." + Thread.currentThread().getName());
        }
    }

    public void consume() throws InterruptedException {

        final Scanner scanner = new Scanner(System.in);
        Thread.sleep(2000);

        synchronized (lock2) {
            System.out.println("Waiting for return key.");
            scanner.nextLine();
            System.out.println("Return key pressed.");
            lock2.notify();
            Thread.sleep(5000);
        }
    }

    public static void main(final String[] args) throws InterruptedException {

        final Processor processor = new Processor();

        final Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Producer 1");
        final Thread t3 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Producer 2");
        final Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    processor.consume();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer");

        t1.start();
        t2.start();
        t3.start();
    }
}

Output:

Producer thread running ....
Producer thread running ....
Waiting for return key.


Return key pressed.

Note: Both producers keep waiting for notifying you need to terminate program manually.


Kindly provide your valuable feedback in comment box.

No comments:

Post a Comment