Manufacturer - Consumer Threading in Java

I want to write a program using multi-threaded wait and notification methods in Java.
This program has a stack (max-length = 5). The producer generates the number forever and puts it on the stack, and the consumer selects it from the stack. When the stack is full, the producer must wait, and when the stack is empty, consumers must wait.
The problem is that it starts only once, I mean, when it produces 5 numbers, which it stops, but I put the start methods while the (true) block works without interception, but it is not.
Here is what I have tried so far. Manufacturer Class:

package trail; import java.util.Random; import java.util.Stack; public class Thread1 implements Runnable { int result; Random rand = new Random(); Stack<Integer> A = new Stack<>(); public Thread1(Stack<Integer> A) { this.A = A; } public synchronized void produce() { while (A.size() >= 5) { System.out.println("List is Full"); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } result = rand.nextInt(10); System.out.println(result + " produced "); A.push(result); System.out.println(A); this.notify(); } @Override public void run() { System.out.println("Producer get started"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } while (true) { produce(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } 

And the consumer:

 package trail; import java.util.Stack; public class Thread2 implements Runnable { Stack<Integer> A = new Stack<>(); public Thread2(Stack<Integer> A) { this.A = A; } public synchronized void consume() { while (A.isEmpty()) { System.err.println("List is empty" + A + A.size()); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.err.println(A.pop() + " Consumed " + A); this.notify(); } @Override public void run() { System.out.println("New consumer get started"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } while (true) { consume(); } } } 

and here is the main method:

 public static void main(String[] args) { Stack<Integer> stack = new Stack<>(); Thread1 thread1 = new Thread1(stack);// p Thread2 thread2 = new Thread2(stack);// c Thread A = new Thread(thread1); Thread B = new Thread(thread2); Thread C = new Thread(thread2); A.start(); B.start(); C.start(); } 
+4
source share
9 answers

You should synchronize on the stack instead of pushing it at the method level, try this code.

Also, do not initialize the stack in your stream classes, since you pass them in the constructor from the main class, so this is not necessary.

Always try not to mark any method with a synchronized keyword, and not try to put a critical section of code in a synchronized block, because the larger the size of your synchronized area will affect performance more.

So, always put only this code in a synchronized block that needs thread safety.

Manufacturer Code

 public void produce() { synchronized (A) { while (A.size() >= 5) { System.out.println("List is Full"); try { A.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } result = rand.nextInt(10); System.out.println(result + " produced "); A.push(result); System.out.println("stack ---"+A); A.notifyAll(); } } 

User Code:

 public void consume() { synchronized (A) { while (A.isEmpty()) { System.err.println("List is empty" + A + A.size()); try { System.err.println("wait"); A.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.err.println(A.pop() + " Consumed " + A); A.notifyAll(); } } 
+2
source

Your consumer and your manufacturer are synchronized at different sites and do not block each other. If this works, I believe it is an accident.

Read java.util.concurrent.BlockingQueue and java.util.concurrent.ArrayBlockingQueue . They provide you with a more modern and easy way to implement this template.

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

+2
source

I think it will be better to understand and deal with synchronization in general if you try to separate the three things that are currently mixed:

  • The task that will do the actual work. The names for the Thread1 and Thread2 are misleading. They are not Thread objects, but in fact they are tasks or tasks that implement the Runnable interface that you pass to Thread objects.

  • The theme object itself, which you create basically

  • A generic object that encapsulates synchronized operations / logic in a queue, stack, etc. This object will be shared between tasks. And inside this general object, you will be engaged in add / delete operations (either with synchronized blocks or with synchronized methods). Currently (as already indicated), synchronization is performed according to the task itself (i.e., each task waits and notifies about its own lock and nothing happens). When you separate the problems, that is, let one class do this correctly, it will eventually become clear where the problem is.

+2
source

Try the following:

 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class CircularArrayQueue<T> { private volatile Lock rwLock = new ReentrantLock(); private volatile Condition emptyCond = rwLock.newCondition(); private volatile Condition fullCond = rwLock.newCondition(); private final int size; private final Object[] buffer; private volatile int front; private volatile int rare; /** * @param size */ public CircularArrayQueue(int size) { this.size = size; this.buffer = new Object[size]; this.front = -1; this.rare = -1; } public boolean isEmpty(){ return front == -1; } public boolean isFull(){ return (front == 0 && rare == size-1) || (front == rare + 1); } public void enqueue(T item){ try { // get a write lock rwLock.lock(); // if the Q is full, wait the write lock if(isFull()) fullCond.await(); if(rare == -1){ rare = 0; front = 0; } else if(rare == size - 1){ rare = 0; } else { rare ++; } buffer[rare] = item; //System.out.println("Added\t: " + item); // notify the reader emptyCond.signal(); } catch(InterruptedException e){ e.printStackTrace(); } finally { // unlock the write lock rwLock.unlock(); } } public T dequeue(){ T item = null; try{ // get the read lock rwLock.lock(); // if the Q is empty, wait the read lock if(isEmpty()) emptyCond.await(); item = (T)buffer[front]; //System.out.println("Deleted\t: " + item); if(front == rare){ front = rare = -1; } else if(front == size - 1){ front = 0; } else { front ++; } // notify the writer fullCond.signal(); } catch (InterruptedException e){ e.printStackTrace(); } finally{ // unlock read lock rwLock.unlock(); } return item; } } 
+2
source

You can use the Java awesome java.util.concurrent package and its classes.

You can easily implement a manufacturer problem using BlockingQueue . A BlockingQueue already supports operations that are waiting for the queue to become empty when the item is retrieved and to wait for the space to become available in the queue when the item is stored.

Without a BlockingQueue , every time we queue data on the producer side, we need to check if the queue is full, and if it is full, wait a while, repeat the check and continue. Similarly, on the part of consumers, we would need to check whether the queue is empty, and if empty, wait a while, repeat the check and continue. However, with BlockingQueue we do not have to write any additional logic than just adding data from the Producer and polling data from the consumer.

Read More From:

http://javawithswaranga.blogspot.in/2012/05/solving-producer-consumer-problem-in.html

http://www.javajee.com/producer-consumer-problem-in-java-using-blockingqueue

0
source

use BlockingQueue, LinkedBlockingQueue, it was very simple. http://developer.android.com/reference/java/util/concurrent/BlockingQueue.html

0
source
 package javaapplication; import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; public class ProducerConsumer { public static Object lock = new Object(); public static Stack stack = new Stack(); public static void main(String[] args) { Thread producer = new Thread(new Runnable() { int i = 0; @Override public void run() { do { synchronized (lock) { while (stack.size() >= 5) { try { lock.wait(); } catch (InterruptedException e) { } } stack.push(++i); if (stack.size() >= 5) { System.out.println("Released lock by producer"); lock.notify(); } } } while (true); } }); Thread consumer = new Thread(new Runnable() { @Override public void run() { do { synchronized (lock) { while (stack.empty()) { try { lock.wait(); } catch (InterruptedException ex) { Logger.getLogger(ProdCons1.class.getName()).log(Level.SEVERE, null, ex); } } while(!stack.isEmpty()){ System.out.println("stack : " + stack.pop()); } lock.notifyAll(); } } while (true); } }); producer.start(); consumer.start(); } } 
0
source

Have a look at this sample code:

 import java.util.concurrent.*; import java.util.Random; public class ProducerConsumerMulti { public static void main(String args[]){ BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<Integer>(); Thread prodThread = new Thread(new Producer(sharedQueue,1)); Thread consThread1 = new Thread(new Consumer(sharedQueue,1)); Thread consThread2 = new Thread(new Consumer(sharedQueue,2)); prodThread.start(); consThread1.start(); consThread2.start(); } } class Producer implements Runnable { private final BlockingQueue<Integer> sharedQueue; private int threadNo; private Random rng; public Producer(BlockingQueue<Integer> sharedQueue,int threadNo) { this.threadNo = threadNo; this.sharedQueue = sharedQueue; this.rng = new Random(); } @Override public void run() { while(true){ try { int number = rng.nextInt(100); System.out.println("Produced:" + number + ":by thread:"+ threadNo); sharedQueue.put(number); Thread.sleep(100); } catch (Exception err) { err.printStackTrace(); } } } } class Consumer implements Runnable{ private final BlockingQueue<Integer> sharedQueue; private int threadNo; public Consumer (BlockingQueue<Integer> sharedQueue,int threadNo) { this.sharedQueue = sharedQueue; this.threadNo = threadNo; } @Override public void run() { while(true){ try { int num = sharedQueue.take(); System.out.println("Consumed: "+ num + ":by thread:"+threadNo); Thread.sleep(100); } catch (Exception err) { err.printStackTrace(); } } } } 

Notes:

  • Launched one Producer and two Consumers according to your problem statement
  • Producer will produce random numbers from 0 to 100 in an infinite loop.
  • Consumer will consume these numbers in an infinite loop
  • Both Producer and Consumer exchange lock and thread LinkedBlockingQueue , which is thread safe. You can remove the wait () and notify () methods if you use these extended parallel constructs.
0
source

It looks like you missed something wait() , notify() and synchronized . See this example , this should help you.

-one
source

Source: https://habr.com/ru/post/1496750/


All Articles