Platinum Partner
java,languages,tips and tricks,clojure

Clojure, Java, and Sleeping Barbers

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);
		
		shop.open();
		
		executor.execute(progressTracker);
		executor.execute(barber);
		executor.execute(customerGenerator);
		executor.shutdown();
		
		Thread.sleep(SHOP_RUNTIME_MILLIS);
		
		shop.close();
	}

	private void close() {
		shopOpen.set(false);
	}

	private void open() {
		shopOpen.set(true);
	}

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

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

	public void recordHaircut() {
		totalHaircuts.incrementAndGet();
	}

	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.

 

Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

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

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}