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

public class WaitNotifyPenyangga {
    // Penyangga satu slot: taruh harus menunggu bila slot terisi,
    // ambil harus menunggu bila slot kosong. Seluruh pencatatan kronologi
    // dilakukan DI DALAM monitor sehingga urutannya terjamin.
    private static class Penyangga {
        private int nilai;
        private boolean terisi = false;
        private final List<String> kronologi;

        Penyangga(List<String> kronologi) {
            this.kronologi = kronologi;
        }

        public synchronized void taruh(int v) throws InterruptedException {
            while (terisi) {
                wait(); // melepas monitor sambil menunggu slot dikosongkan
            }
            nilai = v;
            terisi = true;
            kronologi.add("taruh " + v);
            notifyAll(); // bangunkan semua penunggu monitor ini
        }

        public synchronized int ambil() throws InterruptedException {
            while (!terisi) {
                wait(); // melepas monitor sambil menunggu slot diisi
            }
            terisi = false;
            kronologi.add("ambil " + nilai);
            notifyAll(); // bangunkan semua penunggu monitor ini
            return nilai;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        List<String> kronologi = new ArrayList<>();
        Penyangga penyangga = new Penyangga(kronologi);

        Thread produsen = new Thread(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    penyangga.taruh(i);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "produsen");

        Thread konsumen = new Thread(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    penyangga.ambil();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "konsumen");

        produsen.start();
        konsumen.start();
        produsen.join();
        konsumen.join();

        // Kronologi dicetak SETELAH kedua thread selesai: deterministik.
        for (String baris : kronologi) {
            System.out.println(baris);
        }
    }
}
