class FullException extends Exception { FullException(String msg) { super(msg); } } class Box { private T[] items = (T[]) new Object[3]; private int count = 0; synchronized void add(T item) throws FullException, InterruptedException { if (count == items.length) throw new FullException("Box is full"); while (count == items.length) wait(); items[count++] = item; notifyAll(); } synchronized T retrieve() throws InterruptedException { while (count == 0) wait(); T item = items[--count]; notifyAll(); return item; } boolean isEmpty() { return count == 0; } void clear() { count = 0; } } class Student { String name; Student(String name) { this.name = name; } public String toString() { return name; } } public class Main { public static void main(String[] args) throws Exception { Box intBox = new Box<>(); Box strBox = new Box<>(); Box studentBox = new Box<>(); Thread t1 = new Thread(() -> { try { intBox.add(1); intBox.add(2); intBox.add(3); System.out.println(intBox.retrieve()); } catch (Exception e) { e.printStackTrace(); } }); Thread t2 = new Thread(() -> { try { strBox.add("Hello"); System.out.println(strBox.retrieve()); } catch (Exception e) { e.printStackTrace(); } }); Thread t3 = new Thread(() -> { try { studentBox.add(new Student("Alice")); System.out.println(studentBox.retrieve()); } catch (Exception e) { e.printStackTrace(); } }); t1.start(); t2.start(); t3.start(); } }