Last active
November 28, 2020 21:22
-
-
Save Dainerx/d72f26fb37ae926d4c67c6fdcca507a0 to your computer and use it in GitHub Desktop.
Simulating a chapatti store in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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