Producer Consumer Program using wait() and notify() in Java

做~自己de王妃 提交于 2019-12-06 15:50:06

You can not run two thread in synchronized block with same object. When one method is running another method can not run until another thread call wait method.

To solve this problem you should just put add and remove in synchronized block. For more information see this.

Bhupendra Singh

Producer and Consumer problem is the classic example of multiple-process synchronization problem. This describes two process, producer and consumer which share the common resources, buffer. Producer job is to generate data and put it into a buffer and consumer job is consume the generated data and remove from the buffer.

Producer must ensure that no element should be added when buffer is full, it should call wait() until consumer consume some data and notify to the producer thread AND consumer must ensure that it should not try to remove item from buffer when it is already empty, it should call wait() which simply waits until producer generate data and add it into buffer and notify to the consumer using notify or notifyAll.

This problem can be solved using BlockingQueue interface which do manage this producer and consumer implementation own.

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/*
 * To change this license header, choose License Headers in Project `Properties`.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author sakshi
 */
public class ThreadProducer {

    static List<Integer> list = new ArrayList<Integer>();

    static class Producer implements Runnable {

        List<Integer> list;

        public Producer(List<Integer> list) {
            this.list = list;
        }

        @Override
        public void run() {
            synchronized (list) {
                for (int i = 0; i < 10; i++) {
                    if (list.size() >= 1) {
                        try {
                            System.out.println("producer is waiting ");
                            list.wait();
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }

                    System.out.println("produce=" + i);
                    list.add(i);
                    list.notifyAll();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }

            }

            //To change body of generated methods, choose Tools | Templates.
        }

    }

    static class Consumer implements Runnable {

        List<Integer> list;

        public Consumer(List<Integer> list) {
            this.list = list;
        }

        @Override
        public void run() {

            synchronized (list) {
                for (int i = 0; i < 10; i++) {

                    while (list.isEmpty()) {
                        System.out.println("Consumer is waiting");
                        try {
                            list.wait();
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();;
                        }

                    }

                    int k = list.remove(0);
                    System.out.println("consume=" + k);
                    list.notifyAll();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }

                }

            }
        }

    }

    public static void main(String[] args) {
        Thread producer = new Thread(new Producer(list));
        Thread consumer = new Thread(new Consumer(list));
        producer.start();
        consumer.start();

    }
}

Output:

produce=0
producer is waiting 
consume=0
Consumer is waiting
produce=1
producer is waiting 
consume=1
Consumer is waiting
produce=2
producer is waiting 
consume=2
Consumer is waiting
produce=3
producer is waiting 
consume=3
Consumer is waiting
produce=4
producer is waiting 
consume=4
Consumer is waiting
produce=5
producer is waiting 
consume=5
Consumer is waiting
produce=6
producer is waiting 
consume=6
Consumer is waiting
produce=7
producer is waiting 
consume=7
Consumer is waiting
produce=8
producer is waiting 
consume=8
Consumer is waiting
produce=9
consume=9

class Resources {

private final int capacity = 2;
public static int value = 0;

LinkedList < Integer > list;

Resources() {
    list = new LinkedList < > ();
}

void consume() throws InterruptedException {
    while (true) {
        synchronized(this) {
            while (list.size() == 0) {
                wait();
            }
            int val = list.removeFirst();
            System.out.println("Value consumed:" + val);
            notify();
            //Thread.sleep(1000);
        }
    }
}

void produce() throws InterruptedException {
    while (true) {
        synchronized(this) {
            while (list.size() == capacity) {
                wait();
            }
            System.out.println("Value produced:" + value);
            list.add(value++);
            notify();
            Thread.sleep(1000);

        }
    }
}

}

class MyThread5 extends Thread {

Resources rs;
String name;

public String getNames() {
    return name;
}

public MyThread5(Resources rs, String name) {
    this.rs = rs;
    this.name = name;
}

@Override
public void run() {
    if (this.getNames().equals("Producer")) {
        try {
            this.rs.produce();
        } catch (InterruptedException ex) {
            Logger.getLogger(MyThread5.class.getName()).log(Level.SEVERE, null, ex);
        }
    } else {
        try {
            this.rs.consume();
        } catch (InterruptedException ex) {
            Logger.getLogger(MyThread5.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

}

public class ProducerConsumerExample {

public static void main(String[] args) {
    try {
        Resources rs = new Resources();
        MyThread5 m1 = new MyThread5(rs, "Producer");
        MyThread5 m2 = new MyThread5(rs, "Consumer");
        m1.start();
        m2.start();

        m1.join();
        m2.join();
    } catch (InterruptedException ex) {
        Logger.getLogger(ProducerConsumerExample.class.getName()).log(Level.SEVERE, null, ex);
    }

}

}

Don't use list.size() == 10 , instead you can check list.size == 1.

For producer produced, one wait for the other one till consumer consumes. Refer this Producer Consumer Problem - Solution using wait and notify In Java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!