Skip to content

Instantly share code, notes, and snippets.

@Dainerx
Last active November 28, 2020 21:22
Show Gist options
  • Save Dainerx/d72f26fb37ae926d4c67c6fdcca507a0 to your computer and use it in GitHub Desktop.
Save Dainerx/d72f26fb37ae926d4c67c6fdcca507a0 to your computer and use it in GitHub Desktop.
Simulating a chapatti store in Java
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ChapattiStore {
// Simple builder class for the store
public static class Builder {
private boolean verbose;
private int chappatiToMake;
private int bakers;
private int bakeMeanTime;
private int bakeStdDeviation;
private int makers;
private int makeMeanTime;
private int makeStdDeviation;
private int packageMeanTime;
private int packageStdDeviation;
public Builder verbose(boolean verbose) {
this.verbose = verbose;
return this;
}
public Builder chappatiToMake(int chappatiToMake) {
this.chappatiToMake = chappatiToMake;
return this;
}
public Builder bakers(int bakers) {
this.bakers = bakers;
return this;
}
public Builder bakeMeanTime(int bakeMeanTime) {
this.bakeMeanTime = bakeMeanTime;
return this;
}
public Builder bakeStdDeviation(int bakeStdDeviation) {
this.bakeStdDeviation = bakeMeanTime;
return this;
}
public Builder makers(int makers) {
this.makers = makers;
return this;
}
public Builder makeMeanTime(int makeMeanTime) {
this.makeMeanTime = makeMeanTime;
return this;
}
public Builder makeStdDeviation(int makeStdDeviation) {
this.makeStdDeviation = makeStdDeviation;
return this;
}
public Builder packageMeanTime(int packageMeanTime) {
this.packageMeanTime = packageMeanTime;
return this;
}
public Builder packageStdDeviation(int packageStdDeviation) {
this.packageStdDeviation = packageStdDeviation;
return this;
}
public ChapattiStore build() {
ChapattiStore chapattiStore = new ChapattiStore();
chapattiStore.verbose = this.verbose;
chapattiStore.chappatiToMake = this.chappatiToMake;
chapattiStore.bakers = this.bakers;
chapattiStore.bakeMeanTime = this.bakeMeanTime;
chapattiStore.bakeStdDeviation = this.bakeStdDeviation;
chapattiStore.makers = this.makers;
chapattiStore.makeMeanTime = this.makeMeanTime;
chapattiStore.makeStdDeviation = this.makeStdDeviation;
chapattiStore.packageMeanTime = this.packageMeanTime;
chapattiStore.packageStdDeviation = this.packageStdDeviation;
return chapattiStore;
}
}
private boolean verbose; // True for thread progress logs
private int chappatiToMake; // number of chappati to make
private int bakers; // number of bakers
private int bakeMeanTime; // mean time to prepare dough for one chappati - in ms
private int bakeStdDeviation; // standard deviation to prepare dough for one chappati - in ms
private int makers; // number of chappati makers
private int makeMeanTime; // mean time to make one chappati with baked dough- in ms
private int makeStdDeviation; // standard deviation to make one chappati with baked dough - in ms
private int packageMeanTime; // mean time to package one chapatti - in ms
private int packageStdDeviation; // standard deviation top package one chapatti - in ms
private BlockingQueue<Integer> dough;
private BlockingQueue<Integer> baked;
private BlockingQueue<Integer> made;
/*
work blocks the thread invoked for a period of time
that is normally distributed around mean with a standard deviation of stddev.
*/
private int work(int mean, int stdDeviation) throws InterruptedException {
Random r = new Random();
int delay = (int) r.nextGaussian() * stdDeviation + mean;
if (delay < 0) delay = mean;
Thread.sleep(delay);
return delay;
}
// Bake a chappati and send it to the baked queue.
private void baker() throws InterruptedException {
// Take dough
var d = dough.take();
if (verbose) {
System.out.println("baking " + d);
}
work(bakeMeanTime, bakeStdDeviation);
// Send baked dough after work
baked.put(d);
}
// Retrieve from the baked queue a dough and make a chappati with it.
private void maker() throws InterruptedException {
// Take a baked dough
var bakedDough = baked.take();
if (verbose) {
System.out.println("making " + bakedDough);
}
work(makeMeanTime, makeStdDeviation);
// Send a made chapatti after work
made.put(bakedDough);
}
// Package chapatti and sell them
private void packager() throws InterruptedException {
for (int i = 0; i < chappatiToMake; i++) {
var chapattiReady = made.take();
if (verbose) {
System.out.println("packaging " + chapattiReady);
}
work(packageMeanTime, packageStdDeviation);
if (verbose) {
System.out.println("selling " + chapattiReady);
}
}
}
public float run() throws InterruptedException {
dough = new LinkedBlockingQueue<>();
baked = new LinkedBlockingQueue<>();
made = new LinkedBlockingQueue<>();
for (int i = 0; i < chappatiToMake; i++) {
dough.put(i);
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < bakers; i++) {
Runnable bake = () -> {
while (true) {
try {
baker();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t = new Thread(bake);
t.start();
}
for (int i = 0; i < makers; i++) {
Runnable make = () -> {
while (true) {
try {
maker();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t = new Thread(make);
t.start();
}
packager();
return System.currentTimeMillis() - startTime;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(String.format("Baking{Bakers:%d,BakeStdDev:%dms,BakeMeanTime:%dms}\n",
bakers, bakeStdDeviation, bakeMeanTime));
stringBuilder.append(String.format("Making{Makers:%d,MakeStdDev:%dms,MakeMeanTime:%dms}\n",
makers, makeStdDeviation, makeMeanTime));
stringBuilder.append(String.format("Packaging{PackageMeanTime:%dms,PackageStdDev:%dms}\n",
packageStdDeviation, packageMeanTime));
return stringBuilder.toString();
}
public static void main(String[] args) throws InterruptedException {
Builder builder = new Builder();
// Change the below values - read the comments for attributes above
builder.verbose(false).chappatiToMake(10)
.bakers(5).bakeMeanTime(500).bakeStdDeviation(10)
.makers(5).makeMeanTime(200).makeStdDeviation(10)
.packageMeanTime(100).packageStdDeviation(10);
ChapattiStore chapattiStore = builder.build();
System.out.printf("We closed, took %.2fs to prepare %d chappatis.\n%n", chapattiStore.run() / 1000, chapattiStore.chappatiToMake);
System.out.print(chapattiStore);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment