import java.util.concurrent.ConcurrentLinkedQueue;

public class Reentransi {
    // Antrean kejadian: urutan sebenarnya dijaga happens-before tiapa offer,
    // lalu seluruh isi dicetak setelah kedua thread selesai.
    private static final ConcurrentLinkedQueue<String> kejadian = new ConcurrentLinkedQueue<>();

    private static class Layanan {
        public synchronized void prosesUtama(String nama) {
            kejadian.add(nama + " masuk prosesUtama");
            try {
                Thread.sleep(100); // pegang monitor selama 100 ms
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
            prosesTambahan(nama); // method synchronized lain pada objek yang sama
            kejadian.add(nama + " keluar prosesUtama");
        }

        public synchronized void prosesTambahan(String nama) {
            kejadian.add(nama + " masuk prosesTambahan");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Layanan layanan = new Layanan();

        Thread a = new Thread(() -> layanan.prosesUtama("pekerja-A"), "pekerja-A");
        Thread b = new Thread(() -> layanan.prosesTambahan("pekerja-B"), "pekerja-B");

        a.start();
        b.start();
        a.join();
        b.join();

        for (String baris : kejadian) {
            System.out.println(baris);
        }
    }
}
