Over a million developers have joined DZone.
Platinum Partner

Clojure, Java, and Sleeping Barbers

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

My friend Matt wrote a pretty rad (yep, I used that word) implementation of the “sleeping barber” program in Clojure. Matt’s code had an almost sentence-like simplicity to it – pithy but expressive — that impressed me.

As we walked through how the program worked, I couldn’t help but wonder about a Java implementation. So, I wrote one.

package name.christianson.mike;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.concurrent.TimeUnit.*;

public class BarberShop {
	public static final int NUM_WAITING_ROOM_CHAIRS = 3;
	public static final long SHOP_RUNTIME_MILLIS = SECONDS.toMillis(10);
	private final static AtomicBoolean shopOpen = new AtomicBoolean();
	private final static AtomicInteger totalHaircuts = new AtomicInteger();
	private final static AtomicInteger lostCustomers = new AtomicInteger();
	private final BlockingQueue<Object> waitingRoom = new LinkedBlockingQueue<>(NUM_WAITING_ROOM_CHAIRS);

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

		ExecutorService executor = Executors.newFixedThreadPool(3);
		Runnable customerGenerator = new CustomerGenerator(shop);
		Runnable barber = new Barber(shop);
		Runnable progressTracker = new ProgressTracker(shop);

	private void close() {

	private void open() {

	public boolean isOpen() {
		return shopOpen.get();

	public boolean seatCustomerInWaitingRoom(Object customer) {
		boolean customerSeated = waitingRoom.offer(customer);
		if(!customerSeated) {
		return customerSeated;
	public Object napUntilCustomerArrives() throws InterruptedException {
		return waitingRoom.take();

	public void recordHaircut() {

	public Object lostCustomers() {
		return lostCustomers.get();

	public Object haircuts() {
		return totalHaircuts.get();


Matt’s is self-contained in one file while mine is split across multiple files. (I opted to not use anonymous/inner classes.) I think we were a bit surprised that the concurrency logic is similar and the ”main” driving section of each implementation follows the same set-up procedure. Perhaps my code was influenced by way of transliteration?

I’m struck by how Matt’s Clojure programs reads somewhat like a story while my Java program reads like instructions for a computer.


The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


Published at DZone with permission of Mike Christianson , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}