Producer Consumer Program using wait() and notify(

2019-06-01 05:43发布

I am doing classic Producer-Consumer problem in Java using low level synchronization and wait() and notify(). I know there are better implementations using structures from java.util.concurrent package but my problem revolves around low level implementation:

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

    static Object obj = new Object();

    public static void producer() throws InterruptedException {
        synchronized (obj) {
            while (true) {
                if (list.size() == 10) {
                    System.out.println("Queue full.. Waiting to Add");
                    obj.wait();
                } else {
                    int value = new Random().nextInt(100);
                    if (value <= 10) {
                        Thread.sleep(200);
                        System.out.println("The element added was : " + value);
                        list.add(value);
                        obj.notify();
                    }
                }
            }
        }

    }

    public static void consumer() throws InterruptedException {
        synchronized (obj) {
            while (true) {
                Thread.sleep(500);
                if (list.size() == 0) {
                    System.out.println("Queue is empty...Waiting to remove");
                    obj.wait();
                } else {
                    System.out.println("The element removed was : "
                            + list.remove(0));
                    obj.notify();
                }
            }
        }

    }

There are 2 threads in the program, 1 each for producer and consumer specifically. The code works just fine.

The only issue is that producer goes on to produce messages until the maximum at once (until size is 10 for the list), and consumer consumes all 10 at once.

How can I make producer and consumer work at the same time?

This is the sample output:

The element added was : 4
The element added was : 0
The element added was : 0
The element added was : 4
The element added was : 3
The element added was : 1
The element added was : 10
The element added was : 10
The element added was : 3
The element added was : 9
Queue full.. Waiting to Add
The element removed was : 4
The element removed was : 0
The element removed was : 0
The element removed was : 4
The element removed was : 3
The element removed was : 1
The element removed was : 10
The element removed was : 10
The element removed was : 3
The element removed was : 9
Queue is empty...Waiting to remove

Edit: Here is the corrected code:

private static ArrayList<Integer> list = new ArrayList<Integer>();
    private static Object obj = new Object();

    public static void producer() throws InterruptedException {
        while (true) {
            Thread.sleep(500);
            if (list.size() == 10) {
                System.out.println("Waiting to add");
                synchronized (obj) {
                    obj.wait();
                }
            }
            synchronized (obj) {
                int value = new Random().nextInt(10);
                list.add(value);
                System.out.println("Added to list: " + value);
                obj.notify();
            }
        }
    }

    public static void consumer() throws InterruptedException {
        while (true) {
            Thread.sleep(500);
            if (list.size() == 0) {
                System.out.println("Waiting to remove");
                synchronized (obj) {
                    obj.wait();
                }
            }
            synchronized (obj) {
                int removed = list.remove(0);
                System.out.println("Removed from list: " + removed);
                obj.notify();
            }
        }
    }

4条回答
男人必须洒脱
2楼-- · 2019-06-01 06:34

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.

查看更多
Animai°情兽
3楼-- · 2019-06-01 06:38

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);
    }

}

}

查看更多
家丑人穷心不美
4楼-- · 2019-06-01 06:39

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

查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-06-01 06:41

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
查看更多
登录 后发表回答