/* package whatever; // don't place package name! */

import java.util.ArrayList;
import java.util.List;

class Ideone {
	public static void main(String[] args) {
		new Ideone();
	}
	
	public Ideone() {
		DummyBuffer<String> buf = new DummyBuffer<String>(new ArrayList<String>(), 5);
		
		Thread prod = new Thread(new Producer(buf));
		Thread cons = new Thread(new Consumer(buf));
		
		cons.run();
		prod.run();
				
	}
	
	private class Consumer implements Runnable {
		private DummyBuffer<String> buf;
		
		public Consumer(DummyBuffer<String> buf) {
			this.buf = buf;
		}
		
		@Override
		public void run() {
			buf.take();
		}
	}
	private class Producer implements Runnable {
		private DummyBuffer<String> buf;
		
		public Producer(DummyBuffer<String> buf) {
			this.buf = buf;
		}
		
		@Override
		public void run() {
			System.out.println("Producer there...");
			buf.put("Hello World!");
		}
	}
	
	private class DummyBuffer<T> {
		private final int SIZE;
		private List<T> data;
		
		public DummyBuffer(List<T> sharedData, int maxSize) {
			SIZE = maxSize;
			data = sharedData;
		}
		
		public synchronized T take() {
			while (data.isEmpty()) {
				try {
					System.out.println("waiting... for taking");
					wait();
				}
				catch (InterruptedException e) {
					// Do nothing
				}
			}
			T item = data.remove(data.size() - 1);
			
			notifyAll();
			
			System.out.println("Removed item: " + item);
			return item;
		}
		
		public synchronized void put(T item) {
			while (data.size() >= SIZE) {
				try {
					wait();
				}
				catch (InterruptedException e) {
					// Do nothing
				}
			}
			data.add(item);
			
			System.out.println("notified");
			notifyAll();
			
			System.out.println("Put item: " + item);
		}
	}
}