//There is a problem with this implementation, produce and consume use the same lock. So you can't consume when you're producing, and you can't produce when you're consuming. public class Storage implements StorageInterface{ private final int MAX_NUM = 100; private LinkedList<Object> lists = new LinkedList<Object>(); public void produce(int num){ synchronized (lists) { while(num+lists.size()>MAX_NUM){ try { System.out.println("Temporarily unable to produce "+num+" tasks, the current inventory is: "+lists.size()); lists.wait(); } catch (InterruptedException e) { e.printStackTrace (); } } for(int i=0;i<num;i++){ lists.add(new Object()); System.out.println("Produced "+i+" items, the current inventory is: "+lists.size()); } lists.notifyAll(); } } public void consume(int num){ synchronized (lists) { while(lists.size()<num){ try { System.out.println("Cannot consume "+num+" tasks temporarily, the number of remaining tasks: "+lists.size()); lists.wait(); } catch (InterruptedException e) { e.printStackTrace (); } } for(int i=0;i<lists.size();i++){ lists.remove(i); System.out.println("Consumed "+i+" items, the number of products left: "+lists.size()); } lists.notifyAll(); } } }
The second implementation: an implementation that can both consume and produce. Use BlockingQueue to implement.
public class StorageWithQueen implements StorageInterface{ private final int MAX_NUM = 100; private final BlockingQueue<Object> blockingQueue = new LinkedBlockingQueue<>(MAX_NUM); public void produce(int num) { if(blockingQueue.size()==MAX_NUM){ System.out.println("Temporarily unable to produce "+num+" tasks, the current inventory is: "+blockingQueue.size()); } for(int i=0;i<num;i++){ try { blockingQueue.put(new Object()); System.out.println("Produced "+(i+1)+" items, the current inventory is: "+blockingQueue.size()); } catch (InterruptedException e) { e.printStackTrace (); } } } public void consume(int num){ if(blockingQueue.size()==0){ System.out.println("Cannot consume "+num+" tasks temporarily, the current number of remaining tasks:"+blockingQueue.size()); } for(int i=0;i<blockingQueue.size();i++){ try { blockingQueue.take(); System.out.println("Consumed "+(i+1)+" items, the number of products left: "+blockingQueue.size()); } catch (InterruptedException e) { e.printStackTrace (); } } } }