Removed simulations
This commit is contained in:
parent
06d63a1c04
commit
49ea4c8d4b
@ -1,218 +0,0 @@
|
||||
// lowlevel/BankTellerSimulation.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// Using queues and multithreading
|
||||
// {java BankTellerSimulation 5}
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
// Read-only objects don't require synchronization:
|
||||
class Customer {
|
||||
private final int serviceTime;
|
||||
public Customer(int tm) { serviceTime = tm; }
|
||||
public int getServiceTime() { return serviceTime; }
|
||||
public String toString() {
|
||||
return "[" + serviceTime + "]";
|
||||
}
|
||||
}
|
||||
|
||||
// Teach the customer line to display itself:
|
||||
class CustomerLine extends ArrayBlockingQueue<Customer> {
|
||||
public CustomerLine(int maxLineSize) {
|
||||
super(maxLineSize);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
if(this.size() == 0)
|
||||
return "[Empty]";
|
||||
StringBuilder result = new StringBuilder();
|
||||
for(Customer customer : this)
|
||||
result.append(customer);
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Randomly add customers to a queue:
|
||||
class CustomerSupplier implements Runnable {
|
||||
private CustomerLine customers;
|
||||
private static SplittableRandom rand = new SplittableRandom(47);
|
||||
public CustomerSupplier(CustomerLine cq) {
|
||||
customers = cq;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
TimeUnit.MILLISECONDS.sleep(rand.nextInt(300));
|
||||
customers.put(new Customer(rand.nextInt(1000)));
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("CustomerSupplier interrupted");
|
||||
}
|
||||
System.out.println("CustomerSupplier terminating");
|
||||
}
|
||||
}
|
||||
|
||||
class Teller implements Runnable, Comparable<Teller> {
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
// Customers served during this shift:
|
||||
private int customersServed = 0;
|
||||
private CustomerLine customers;
|
||||
private boolean servingCustomerLine = true;
|
||||
public Teller(CustomerLine cq) { customers = cq; }
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
Customer customer = customers.take();
|
||||
TimeUnit.MILLISECONDS.sleep(
|
||||
customer.getServiceTime());
|
||||
synchronized(this) {
|
||||
customersServed++;
|
||||
while(!servingCustomerLine)
|
||||
wait();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(this + "interrupted");
|
||||
}
|
||||
System.out.println(this + "terminating");
|
||||
}
|
||||
public synchronized void doSomethingElse() {
|
||||
customersServed = 0;
|
||||
servingCustomerLine = false;
|
||||
}
|
||||
public synchronized void serveCustomerLine() {
|
||||
assert !servingCustomerLine:
|
||||
"already serving: " + this;
|
||||
servingCustomerLine = true;
|
||||
notifyAll();
|
||||
}
|
||||
public String toString() {
|
||||
return "Teller " + id + " ";
|
||||
}
|
||||
public String shortString() { return "T" + id; }
|
||||
// Used by priority queue:
|
||||
public synchronized int compareTo(Teller other) {
|
||||
return customersServed < other.customersServed ? -1 :
|
||||
(customersServed == other.customersServed ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
class TellerManager implements Runnable {
|
||||
private ExecutorService exec;
|
||||
private CustomerLine customers;
|
||||
private PriorityQueue<Teller> workingTellers =
|
||||
new PriorityQueue<>();
|
||||
private Queue<Teller> tellersDoingOtherThings =
|
||||
new LinkedList<>();
|
||||
private int adjustmentPeriod;
|
||||
|
||||
public TellerManager(ExecutorService e,
|
||||
CustomerLine customers, int adjustmentPeriod) {
|
||||
exec = e;
|
||||
this.customers = customers;
|
||||
this.adjustmentPeriod = adjustmentPeriod;
|
||||
// Start with a single teller:
|
||||
Teller teller = new Teller(customers);
|
||||
exec.execute(teller);
|
||||
workingTellers.add(teller);
|
||||
}
|
||||
public void adjustTellerNumber() {
|
||||
// This is actually a control system. By adjusting
|
||||
// the numbers, you can reveal stability issues in
|
||||
// the control mechanism.
|
||||
// If line is too long, add another teller:
|
||||
if(customers.size() / workingTellers.size() > 2) {
|
||||
// If tellers are on break or doing
|
||||
// another job, bring one back:
|
||||
if(tellersDoingOtherThings.size() > 0) {
|
||||
Teller teller =
|
||||
tellersDoingOtherThings.remove();
|
||||
teller.serveCustomerLine();
|
||||
workingTellers.offer(teller);
|
||||
return;
|
||||
}
|
||||
// Else create (hire) a new teller
|
||||
Teller teller = new Teller(customers);
|
||||
exec.execute(teller);
|
||||
workingTellers.add(teller);
|
||||
return;
|
||||
}
|
||||
// If line is short enough, remove a teller:
|
||||
if(workingTellers.size() > 1 &&
|
||||
customers.size() / workingTellers.size() < 2)
|
||||
reassignOneTeller();
|
||||
// If there is no line, we only need one teller:
|
||||
if(customers.size() == 0)
|
||||
while(workingTellers.size() > 1)
|
||||
reassignOneTeller();
|
||||
}
|
||||
// Give a teller a different job or a break:
|
||||
private void reassignOneTeller() {
|
||||
Teller teller = workingTellers.poll();
|
||||
teller.doSomethingElse();
|
||||
tellersDoingOtherThings.offer(teller);
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
TimeUnit.MILLISECONDS.sleep(adjustmentPeriod);
|
||||
adjustTellerNumber();
|
||||
System.out.print(customers + " { ");
|
||||
for(Teller teller : workingTellers)
|
||||
System.out.print(teller.shortString() + " ");
|
||||
System.out.println("}");
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(this + "interrupted");
|
||||
}
|
||||
System.out.println(this + "terminating");
|
||||
}
|
||||
@Override
|
||||
public String toString() { return "TellerManager "; }
|
||||
}
|
||||
|
||||
public class BankTellerSimulation {
|
||||
static final int MAX_LINE_SIZE = 50;
|
||||
static final int ADJUSTMENT_PERIOD = 1000;
|
||||
public static void
|
||||
main(String[] args) throws Exception {
|
||||
ExecutorService es = Executors.newCachedThreadPool();
|
||||
// If line is too long, customers will leave:
|
||||
CustomerLine customers =
|
||||
new CustomerLine(MAX_LINE_SIZE);
|
||||
es.execute(new CustomerSupplier(customers));
|
||||
// Manager will add and remove tellers as necessary:
|
||||
es.execute(new TellerManager(
|
||||
es, customers, ADJUSTMENT_PERIOD));
|
||||
if(args.length > 0) // Optional argument
|
||||
TimeUnit.SECONDS.sleep(new Integer(args[0]));
|
||||
else {
|
||||
System.out.println("Press 'Enter' to quit");
|
||||
System.in.read();
|
||||
}
|
||||
es.shutdownNow();
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
[768][193][807][125] { T1 T0 }
|
||||
[125][634][682][267][954][506][639][213] { T2 T0 T1 }
|
||||
[213][592][770][919][552][727][998][902] { T2 T0 T1 }
|
||||
[552][727][998][902][769][373][313][683][177][526] { T3 T2
|
||||
T1 T0 }
|
||||
TellerManager interrupted
|
||||
Teller 3 interrupted
|
||||
CustomerSupplier interrupted
|
||||
Teller 3 terminating
|
||||
Teller 2 interrupted
|
||||
Teller 2 terminating
|
||||
TellerManager terminating
|
||||
Teller 1 interrupted
|
||||
Teller 0 interrupted
|
||||
Teller 0 terminating
|
||||
Teller 1 terminating
|
||||
CustomerSupplier terminating
|
||||
*/
|
@ -1,312 +0,0 @@
|
||||
// lowlevel/CarBuilder.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// A complex example of tasks working together
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
class Car {
|
||||
private final int id;
|
||||
private boolean
|
||||
engine = false, driveTrain = false, wheels = false;
|
||||
public Car(int idn) { id = idn; }
|
||||
// Empty Car object:
|
||||
public Car() { id = -1; }
|
||||
public synchronized int getId() { return id; }
|
||||
public synchronized void addEngine() { engine = true; }
|
||||
public synchronized void addDriveTrain() {
|
||||
driveTrain = true;
|
||||
}
|
||||
public synchronized void addWheels() { wheels = true; }
|
||||
public synchronized String toString() {
|
||||
return "Car " + id + " [" + " engine: " + engine
|
||||
+ " driveTrain: " + driveTrain
|
||||
+ " wheels: " + wheels + " ]";
|
||||
}
|
||||
}
|
||||
|
||||
class CarQueue extends LinkedBlockingQueue<Car> {}
|
||||
|
||||
class ChassisBuilder implements Runnable {
|
||||
private CarQueue carQueue;
|
||||
private int counter = 0;
|
||||
public ChassisBuilder(CarQueue cq) { carQueue = cq; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
// Make chassis:
|
||||
Car c = new Car(counter++);
|
||||
System.out.println("ChassisBuilder created " + c);
|
||||
// Insert into queue
|
||||
carQueue.put(c);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Interrupted: ChassisBuilder");
|
||||
}
|
||||
System.out.println("ChassisBuilder off");
|
||||
}
|
||||
}
|
||||
|
||||
class Assembler implements Runnable {
|
||||
private CarQueue chassisQueue, finishingQueue;
|
||||
private Car car;
|
||||
private CyclicBarrier barrier = new CyclicBarrier(4);
|
||||
private RobotPool robotPool;
|
||||
public
|
||||
Assembler(CarQueue cq, CarQueue fq, RobotPool rp) {
|
||||
chassisQueue = cq;
|
||||
finishingQueue = fq;
|
||||
robotPool = rp;
|
||||
}
|
||||
public Car car() { return car; }
|
||||
public CyclicBarrier barrier() { return barrier; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// Blocks until chassis is available:
|
||||
car = chassisQueue.take();
|
||||
// Hire robots to perform work:
|
||||
robotPool.hire(EngineRobot.class, this);
|
||||
robotPool.hire(DriveTrainRobot.class, this);
|
||||
robotPool.hire(WheelRobot.class, this);
|
||||
barrier.await(); // Until the robots finish
|
||||
// Put car into finishingQueue for further work
|
||||
finishingQueue.put(car);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(
|
||||
"Exiting Assembler via interrupt");
|
||||
} catch(BrokenBarrierException e) {
|
||||
// This one we want to know about
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("Assembler off");
|
||||
}
|
||||
}
|
||||
|
||||
class Reporter implements Runnable {
|
||||
private CarQueue carQueue;
|
||||
public Reporter(CarQueue cq) { carQueue = cq; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
System.out.println(carQueue.take());
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(
|
||||
"Exiting Reporter via interrupt");
|
||||
}
|
||||
System.out.println("Reporter off");
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Robot implements Runnable {
|
||||
private RobotPool pool;
|
||||
protected Assembler assembler;
|
||||
public Robot(RobotPool p) { pool = p; }
|
||||
public Robot assignAssembler(Assembler assembler) {
|
||||
this.assembler = assembler;
|
||||
return this;
|
||||
}
|
||||
private boolean engage = false;
|
||||
public synchronized void engage() {
|
||||
engage = true;
|
||||
notifyAll();
|
||||
}
|
||||
// The part of run() that's different for each robot:
|
||||
protected abstract void performService();
|
||||
public void run() {
|
||||
try {
|
||||
powerDown(); // Wait until needed
|
||||
while(!Thread.interrupted()) {
|
||||
performService();
|
||||
assembler.barrier().await(); // Synchronize
|
||||
// We're done with that job...
|
||||
powerDown();
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(
|
||||
"Exiting " + this + " via interrupt");
|
||||
} catch(BrokenBarrierException e) {
|
||||
// This one we want to know about
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println(this + " off");
|
||||
}
|
||||
private synchronized void
|
||||
powerDown() throws InterruptedException {
|
||||
engage = false;
|
||||
assembler = null; // Disconnect from the Assembler
|
||||
// Put ourselves back in the available pool:
|
||||
pool.release(this);
|
||||
while(engage == false) // Power down
|
||||
wait();
|
||||
}
|
||||
public String toString() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
class EngineRobot extends Robot {
|
||||
public EngineRobot(RobotPool pool) { super(pool); }
|
||||
protected void performService() {
|
||||
System.out.println(this + " installing engine");
|
||||
assembler.car().addEngine();
|
||||
}
|
||||
}
|
||||
|
||||
class DriveTrainRobot extends Robot {
|
||||
public DriveTrainRobot(RobotPool pool) { super(pool); }
|
||||
protected void performService() {
|
||||
System.out.println(this + " installing DriveTrain");
|
||||
assembler.car().addDriveTrain();
|
||||
}
|
||||
}
|
||||
|
||||
class WheelRobot extends Robot {
|
||||
public WheelRobot(RobotPool pool) { super(pool); }
|
||||
protected void performService() {
|
||||
System.out.println(this + " installing Wheels");
|
||||
assembler.car().addWheels();
|
||||
}
|
||||
}
|
||||
|
||||
class RobotPool {
|
||||
// Quietly prevents identical entries:
|
||||
private Set<Robot> pool = new HashSet<>();
|
||||
public synchronized void add(Robot r) {
|
||||
pool.add(r);
|
||||
notifyAll();
|
||||
}
|
||||
public synchronized void
|
||||
hire(Class<? extends Robot> robotType, Assembler d)
|
||||
throws InterruptedException {
|
||||
for(Robot r : pool)
|
||||
if(r.getClass().equals(robotType)) {
|
||||
pool.remove(r);
|
||||
r.assignAssembler(d);
|
||||
r.engage(); // Power it up to do the task
|
||||
return;
|
||||
}
|
||||
wait(); // None available
|
||||
hire(robotType, d); // Try again, recursively
|
||||
}
|
||||
public synchronized void release(Robot r) { add(r); }
|
||||
}
|
||||
|
||||
public class CarBuilder {
|
||||
public static void
|
||||
main(String[] args) throws Exception {
|
||||
CarQueue chassisQueue = new CarQueue(),
|
||||
finishingQueue = new CarQueue();
|
||||
ExecutorService es = Executors.newCachedThreadPool();
|
||||
RobotPool robotPool = new RobotPool();
|
||||
es.execute(new EngineRobot(robotPool));
|
||||
es.execute(new DriveTrainRobot(robotPool));
|
||||
es.execute(new WheelRobot(robotPool));
|
||||
es.execute(new Assembler(
|
||||
chassisQueue, finishingQueue, robotPool));
|
||||
es.execute(new Reporter(finishingQueue));
|
||||
// Start everything running by producing chassis:
|
||||
es.execute(new ChassisBuilder(chassisQueue));
|
||||
TimeUnit.SECONDS.sleep(7);
|
||||
es.shutdownNow();
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
ChassisBuilder created Car 0 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
EngineRobot installing engine
|
||||
Car 0 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 1 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
Car 1 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 2 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
DriveTrainRobot installing DriveTrain
|
||||
WheelRobot installing Wheels
|
||||
EngineRobot installing engine
|
||||
Car 2 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 3 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
DriveTrainRobot installing DriveTrain
|
||||
WheelRobot installing Wheels
|
||||
EngineRobot installing engine
|
||||
Car 3 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 4 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
DriveTrainRobot installing DriveTrain
|
||||
WheelRobot installing Wheels
|
||||
Car 4 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 5 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
Car 5 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 6 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
Car 6 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 7 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
Car 7 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 8 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
Car 8 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 9 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
DriveTrainRobot installing DriveTrain
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
Car 9 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 10 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
DriveTrainRobot installing DriveTrain
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
Car 10 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 11 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
EngineRobot installing engine
|
||||
WheelRobot installing Wheels
|
||||
DriveTrainRobot installing DriveTrain
|
||||
Car 11 [ engine: true driveTrain: true wheels: true ]
|
||||
ChassisBuilder created Car 12 [ engine: false driveTrain:
|
||||
false wheels: false ]
|
||||
DriveTrainRobot installing DriveTrain
|
||||
WheelRobot installing Wheels
|
||||
EngineRobot installing engine
|
||||
Car 12 [ engine: true driveTrain: true wheels: true ]
|
||||
Exiting Assembler via interrupt
|
||||
Exiting EngineRobot via interrupt
|
||||
Exiting WheelRobot via interrupt
|
||||
Exiting DriveTrainRobot via interrupt
|
||||
DriveTrainRobot off
|
||||
Exiting Reporter via interrupt
|
||||
Interrupted: ChassisBuilder
|
||||
Reporter off
|
||||
WheelRobot off
|
||||
EngineRobot off
|
||||
Assembler off
|
||||
ChassisBuilder off
|
||||
*/
|
@ -1,202 +0,0 @@
|
||||
// lowlevel/GreenhouseScheduler.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// Rewriting innerclasses/GreenhouseController.java
|
||||
// to use a ScheduledThreadPoolExecutor
|
||||
// {java GreenhouseScheduler 5000}
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
public class GreenhouseScheduler {
|
||||
private volatile boolean light = false;
|
||||
private volatile boolean water = false;
|
||||
private String thermostat = "Day";
|
||||
public synchronized String getThermostat() {
|
||||
return thermostat;
|
||||
}
|
||||
public synchronized void setThermostat(String value) {
|
||||
thermostat = value;
|
||||
}
|
||||
ScheduledThreadPoolExecutor scheduler =
|
||||
new ScheduledThreadPoolExecutor(10);
|
||||
public void schedule(Runnable event, long delay) {
|
||||
scheduler.schedule(event,delay,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
public void
|
||||
repeat(Runnable event, long initialDelay, long period) {
|
||||
scheduler.scheduleAtFixedRate(
|
||||
event, initialDelay, period, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
class LightOn implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here to
|
||||
// physically turn on the light.
|
||||
System.out.println("Turning on lights");
|
||||
light = true;
|
||||
}
|
||||
}
|
||||
class LightOff implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here to
|
||||
// physically turn off the light.
|
||||
System.out.println("Turning off lights");
|
||||
light = false;
|
||||
}
|
||||
}
|
||||
class WaterOn implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Turning greenhouse water on");
|
||||
water = true;
|
||||
}
|
||||
}
|
||||
class WaterOff implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Turning greenhouse water off");
|
||||
water = false;
|
||||
}
|
||||
}
|
||||
class ThermostatNight implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Thermostat to night setting");
|
||||
setThermostat("Night");
|
||||
}
|
||||
}
|
||||
class ThermostatDay implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Put hardware control code here.
|
||||
System.out.println("Thermostat to day setting");
|
||||
setThermostat("Day");
|
||||
}
|
||||
}
|
||||
class Bell implements Runnable {
|
||||
@Override
|
||||
public void run() { System.out.println("Bing!"); }
|
||||
}
|
||||
class Terminate implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Terminating");
|
||||
scheduler.shutdownNow();
|
||||
// Must start a separate task to do this job,
|
||||
// since the scheduler was shut down:
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
for(DataPoint d : data)
|
||||
System.out.println(d);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
// New feature: data collection
|
||||
static class DataPoint {
|
||||
final Calendar time;
|
||||
final double temperature;
|
||||
final double humidity;
|
||||
public DataPoint(Calendar d, double temp, double hum) {
|
||||
time = d;
|
||||
temperature = temp;
|
||||
humidity = hum;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return time.getTime() +
|
||||
String.format(
|
||||
" temperature: %1$.1f humidity: %2$.2f",
|
||||
temperature, humidity);
|
||||
}
|
||||
}
|
||||
private Calendar lastTime = Calendar.getInstance();
|
||||
{ // Adjust date to the half hour
|
||||
lastTime.set(Calendar.MINUTE, 30);
|
||||
lastTime.set(Calendar.SECOND, 00);
|
||||
}
|
||||
private double lastTemp = 65.0f;
|
||||
private int tempDirection = +1;
|
||||
private double lastHumidity = 50.0f;
|
||||
private int humidityDirection = +1;
|
||||
private SplittableRandom rand = new SplittableRandom(47);
|
||||
List<DataPoint> data = Collections.synchronizedList(
|
||||
new ArrayList<>());
|
||||
class CollectData implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Collecting data");
|
||||
synchronized(GreenhouseScheduler.this) {
|
||||
// Pretend the interval is longer than it is:
|
||||
lastTime.set(Calendar.MINUTE,
|
||||
lastTime.get(Calendar.MINUTE) + 30);
|
||||
// One in 5 chances of reversing the direction:
|
||||
if(rand.nextInt(5) == 4)
|
||||
tempDirection = -tempDirection;
|
||||
// Store previous value:
|
||||
lastTemp +=
|
||||
tempDirection * (1.0f + rand.nextDouble());
|
||||
if(rand.nextInt(5) == 4)
|
||||
humidityDirection = -humidityDirection;
|
||||
lastHumidity +=
|
||||
humidityDirection * rand.nextDouble();
|
||||
// Calendar must be cloned, otherwise all
|
||||
// DataPoints hold references to same lastTime.
|
||||
// For basic object like Calendar, clone() is OK.
|
||||
data.add(new DataPoint((Calendar)lastTime.clone(),
|
||||
lastTemp, lastHumidity));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
GreenhouseScheduler gh = new GreenhouseScheduler();
|
||||
gh.schedule(gh.new Terminate(), 5000);
|
||||
// Former "Restart" class not necessary:
|
||||
gh.repeat(gh.new Bell(), 0, 1000);
|
||||
gh.repeat(gh.new ThermostatNight(), 0, 2000);
|
||||
gh.repeat(gh.new LightOn(), 0, 200);
|
||||
gh.repeat(gh.new LightOff(), 0, 400);
|
||||
gh.repeat(gh.new WaterOn(), 0, 600);
|
||||
gh.repeat(gh.new WaterOff(), 0, 800);
|
||||
gh.repeat(gh.new ThermostatDay(), 0, 1400);
|
||||
gh.repeat(gh.new CollectData(), 500, 500);
|
||||
}
|
||||
}
|
||||
/* Output: (First and Last 10 Lines)
|
||||
Bing!
|
||||
Thermostat to night setting
|
||||
Turning on lights
|
||||
Turning off lights
|
||||
Turning greenhouse water on
|
||||
Turning greenhouse water off
|
||||
Thermostat to day setting
|
||||
Turning on lights
|
||||
Turning on lights
|
||||
Turning off lights
|
||||
...________...________...________...________...
|
||||
Terminating
|
||||
Wed Jul 27 11:00:00 MDT 2016 temperature: 66.3 humidity:
|
||||
50.20
|
||||
Wed Jul 27 11:30:00 MDT 2016 temperature: 67.3 humidity:
|
||||
51.02
|
||||
Wed Jul 27 12:00:00 MDT 2016 temperature: 68.8 humidity:
|
||||
51.82
|
||||
Wed Jul 27 12:30:00 MDT 2016 temperature: 70.0 humidity:
|
||||
52.19
|
||||
Wed Jul 27 13:00:00 MDT 2016 temperature: 71.5 humidity:
|
||||
52.99
|
||||
Wed Jul 27 13:30:00 MDT 2016 temperature: 73.0 humidity:
|
||||
53.32
|
||||
Wed Jul 27 14:00:00 MDT 2016 temperature: 74.4 humidity:
|
||||
53.99
|
||||
Wed Jul 27 14:30:00 MDT 2016 temperature: 75.5 humidity:
|
||||
54.40
|
||||
Wed Jul 27 15:00:00 MDT 2016 temperature: 76.8 humidity:
|
||||
53.96
|
||||
*/
|
@ -1,132 +0,0 @@
|
||||
// lowlevel/HorseRace.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// Using CyclicBarriers
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
import onjava.Nap;
|
||||
|
||||
class Horse implements Runnable {
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
private int strides = 0;
|
||||
private static SplittableRandom rand = new SplittableRandom(47);
|
||||
private static CyclicBarrier barrier;
|
||||
public Horse(CyclicBarrier b) { barrier = b; }
|
||||
public synchronized int getStrides() { return strides; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
synchronized(this) {
|
||||
strides += rand.nextInt(3); // Yeilds 0, 1 or 2
|
||||
}
|
||||
barrier.await();
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
// A legitimate way to exit
|
||||
} catch(BrokenBarrierException e) {
|
||||
// This one we want to know about
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() { return "Horse " + id + " "; }
|
||||
public String tracks() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for(int i = 0; i < getStrides(); i++)
|
||||
s.append("*");
|
||||
s.append(id);
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public class HorseRace {
|
||||
static final int FINISH_LINE = 60;
|
||||
private List<Horse> horses = new ArrayList<>();
|
||||
private ExecutorService exec =
|
||||
Executors.newCachedThreadPool();
|
||||
private CyclicBarrier barrier;
|
||||
public HorseRace(int nHorses, final int pause) {
|
||||
barrier = new CyclicBarrier(nHorses, () -> {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for(int i = 0; i < FINISH_LINE; i++)
|
||||
s.append("="); // The fence on the racetrack
|
||||
System.out.println(s);
|
||||
for(Horse horse : horses)
|
||||
System.out.println(horse.tracks());
|
||||
for(Horse horse : horses)
|
||||
if(horse.getStrides() >= FINISH_LINE) {
|
||||
System.out.println(horse + "won!");
|
||||
exec.shutdownNow();
|
||||
return;
|
||||
}
|
||||
new Nap(pause);
|
||||
});
|
||||
for(int i = 0; i < nHorses; i++) {
|
||||
Horse horse = new Horse(barrier);
|
||||
horses.add(horse);
|
||||
exec.execute(horse);
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
int nHorses = 7;
|
||||
int pause = 200;
|
||||
if(args.length > 0) { // Optional argument
|
||||
int n = new Integer(args[0]);
|
||||
nHorses = n > 0 ? n : nHorses;
|
||||
}
|
||||
if(args.length > 1) { // Optional argument
|
||||
int p = new Integer(args[1]);
|
||||
pause = p > -1 ? p : pause;
|
||||
}
|
||||
new HorseRace(nHorses, pause);
|
||||
}
|
||||
}
|
||||
/* Output: (First and Last 18 Lines)
|
||||
===========================================================
|
||||
=
|
||||
0
|
||||
**1
|
||||
2
|
||||
*3
|
||||
**4
|
||||
*5
|
||||
**6
|
||||
===========================================================
|
||||
=
|
||||
**0
|
||||
***1
|
||||
*2
|
||||
*3
|
||||
****4
|
||||
**5
|
||||
****6
|
||||
===========================================================
|
||||
=
|
||||
**0
|
||||
...________...________...________...________...
|
||||
**********************************************6
|
||||
===========================================================
|
||||
=
|
||||
**************************************************0
|
||||
*************************************************1
|
||||
*********************************************2
|
||||
***********************************************************
|
||||
3
|
||||
*****************************************************4
|
||||
*****************************************************5
|
||||
***********************************************6
|
||||
===========================================================
|
||||
=
|
||||
****************************************************0
|
||||
*************************************************1
|
||||
***********************************************2
|
||||
***********************************************************
|
||||
*3
|
||||
*******************************************************4
|
||||
*******************************************************5
|
||||
***********************************************6
|
||||
Horse 3 won!
|
||||
*/
|
@ -1,94 +0,0 @@
|
||||
// lowlevel/Restaurant.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// The producer-consumer approach to task cooperation
|
||||
import java.util.concurrent.*;
|
||||
|
||||
class Meal {
|
||||
private final int orderNum;
|
||||
public Meal(int orderNum) { this.orderNum = orderNum; }
|
||||
@Override
|
||||
public String toString() { return "Meal " + orderNum; }
|
||||
}
|
||||
|
||||
class WaitPerson implements Runnable {
|
||||
private Restaurant restaurant;
|
||||
public WaitPerson(Restaurant r) { restaurant = r; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
synchronized(this) {
|
||||
while(restaurant.meal == null)
|
||||
wait(); // ... for the chef to produce a meal
|
||||
}
|
||||
System.out.println(
|
||||
"Waitperson got " + restaurant.meal);
|
||||
synchronized(restaurant.chef) {
|
||||
restaurant.meal = null;
|
||||
restaurant.chef.notifyAll(); // Ready for more
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("WaitPerson interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Chef implements Runnable {
|
||||
private Restaurant restaurant;
|
||||
private int count = 0;
|
||||
public Chef(Restaurant r) { restaurant = r; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
synchronized(this) {
|
||||
while(restaurant.meal != null)
|
||||
wait(); // ... for the meal to be taken
|
||||
}
|
||||
if(++count == 10) {
|
||||
System.out.println("Out of food, closing");
|
||||
restaurant.exec.shutdownNow();
|
||||
}
|
||||
System.out.print("Order up! ");
|
||||
synchronized(restaurant.waitPerson) {
|
||||
restaurant.meal = new Meal(count);
|
||||
restaurant.waitPerson.notifyAll();
|
||||
}
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Chef interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Restaurant {
|
||||
Meal meal;
|
||||
ExecutorService exec = Executors.newCachedThreadPool();
|
||||
WaitPerson waitPerson = new WaitPerson(this);
|
||||
Chef chef = new Chef(this);
|
||||
public Restaurant() {
|
||||
exec.execute(chef);
|
||||
exec.execute(waitPerson);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
new Restaurant();
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
Order up! Waitperson got Meal 1
|
||||
Order up! Waitperson got Meal 2
|
||||
Order up! Waitperson got Meal 3
|
||||
Order up! Waitperson got Meal 4
|
||||
Order up! Waitperson got Meal 5
|
||||
Order up! Waitperson got Meal 6
|
||||
Order up! Waitperson got Meal 7
|
||||
Order up! Waitperson got Meal 8
|
||||
Order up! Waitperson got Meal 9
|
||||
Out of food, closing
|
||||
Order up! WaitPerson interrupted
|
||||
Chef interrupted
|
||||
*/
|
@ -1,204 +0,0 @@
|
||||
// lowlevel/ToastOMatic.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// A toaster that uses queues
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
class Toast {
|
||||
public enum Status { DRY, BUTTERED, JAMMED }
|
||||
private Status status = Status.DRY;
|
||||
private final int id;
|
||||
public Toast(int idn) { id = idn; }
|
||||
public void butter() { status = Status.BUTTERED; }
|
||||
public void jam() { status = Status.JAMMED; }
|
||||
public Status getStatus() { return status; }
|
||||
public int getId() { return id; }
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Toast " + id + ": " + status;
|
||||
}
|
||||
}
|
||||
|
||||
class ToastQueue extends LinkedBlockingQueue<Toast> {}
|
||||
|
||||
class Toaster implements Runnable {
|
||||
private ToastQueue toastQueue;
|
||||
private int count = 0;
|
||||
private SplittableRandom rand = new SplittableRandom(47);
|
||||
public Toaster(ToastQueue tq) { toastQueue = tq; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
TimeUnit.MILLISECONDS.sleep(
|
||||
100 + rand.nextInt(500));
|
||||
// Make toast
|
||||
Toast t = new Toast(count++);
|
||||
System.out.println(t);
|
||||
// Insert into queue
|
||||
toastQueue.put(t);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Toaster interrupted");
|
||||
}
|
||||
System.out.println("Toaster off");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply butter to toast:
|
||||
class Butterer implements Runnable {
|
||||
private ToastQueue dryQueue, butteredQueue;
|
||||
public Butterer(ToastQueue dry, ToastQueue buttered) {
|
||||
dryQueue = dry;
|
||||
butteredQueue = buttered;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// Blocks until next piece of toast is available:
|
||||
Toast t = dryQueue.take();
|
||||
t.butter();
|
||||
System.out.println(t);
|
||||
butteredQueue.put(t);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Butterer interrupted");
|
||||
}
|
||||
System.out.println("Butterer off");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply jam to buttered toast:
|
||||
class Jammer implements Runnable {
|
||||
private ToastQueue butteredQueue, finishedQueue;
|
||||
public
|
||||
Jammer(ToastQueue buttered, ToastQueue finished) {
|
||||
butteredQueue = buttered;
|
||||
finishedQueue = finished;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// Blocks until next piece of toast is available:
|
||||
Toast t = butteredQueue.take();
|
||||
t.jam();
|
||||
System.out.println(t);
|
||||
finishedQueue.put(t);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Jammer interrupted");
|
||||
}
|
||||
System.out.println("Jammer off");
|
||||
}
|
||||
}
|
||||
|
||||
// Consume the toast:
|
||||
class Eater implements Runnable {
|
||||
private ToastQueue finishedQueue;
|
||||
private int counter = 0;
|
||||
public Eater(ToastQueue finished) {
|
||||
finishedQueue = finished;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// Blocks until next piece of toast is available:
|
||||
Toast t = finishedQueue.take();
|
||||
// Verify that the toast is coming in order,
|
||||
// and that all pieces are getting jammed:
|
||||
if(t.getId() != counter++ ||
|
||||
t.getStatus() != Toast.Status.JAMMED) {
|
||||
System.out.println(">>>> Error: " + t);
|
||||
System.exit(1);
|
||||
} else
|
||||
System.out.println("Chomp! " + t);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Eater interrupted");
|
||||
}
|
||||
System.out.println("Eater off");
|
||||
}
|
||||
}
|
||||
|
||||
public class ToastOMatic {
|
||||
public static void
|
||||
main(String[] args) throws Exception {
|
||||
ToastQueue dryQueue = new ToastQueue(),
|
||||
butteredQueue = new ToastQueue(),
|
||||
finishedQueue = new ToastQueue();
|
||||
ExecutorService es = Executors.newCachedThreadPool();
|
||||
es.execute(new Toaster(dryQueue));
|
||||
es.execute(new Butterer(dryQueue, butteredQueue));
|
||||
es.execute(new Jammer(butteredQueue, finishedQueue));
|
||||
es.execute(new Eater(finishedQueue));
|
||||
TimeUnit.SECONDS.sleep(5);
|
||||
es.shutdownNow();
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
Toast 0: DRY
|
||||
Toast 0: BUTTERED
|
||||
Toast 0: JAMMED
|
||||
Chomp! Toast 0: JAMMED
|
||||
Toast 1: DRY
|
||||
Toast 1: BUTTERED
|
||||
Toast 1: JAMMED
|
||||
Chomp! Toast 1: JAMMED
|
||||
Toast 2: DRY
|
||||
Toast 2: BUTTERED
|
||||
Toast 2: JAMMED
|
||||
Chomp! Toast 2: JAMMED
|
||||
Toast 3: DRY
|
||||
Toast 3: BUTTERED
|
||||
Toast 3: JAMMED
|
||||
Chomp! Toast 3: JAMMED
|
||||
Toast 4: DRY
|
||||
Toast 4: BUTTERED
|
||||
Toast 4: JAMMED
|
||||
Chomp! Toast 4: JAMMED
|
||||
Toast 5: DRY
|
||||
Toast 5: BUTTERED
|
||||
Toast 5: JAMMED
|
||||
Chomp! Toast 5: JAMMED
|
||||
Toast 6: DRY
|
||||
Toast 6: BUTTERED
|
||||
Toast 6: JAMMED
|
||||
Chomp! Toast 6: JAMMED
|
||||
Toast 7: DRY
|
||||
Toast 7: BUTTERED
|
||||
Toast 7: JAMMED
|
||||
Chomp! Toast 7: JAMMED
|
||||
Toast 8: DRY
|
||||
Toast 8: BUTTERED
|
||||
Toast 8: JAMMED
|
||||
Chomp! Toast 8: JAMMED
|
||||
Toast 9: DRY
|
||||
Toast 9: BUTTERED
|
||||
Toast 9: JAMMED
|
||||
Chomp! Toast 9: JAMMED
|
||||
Toast 10: DRY
|
||||
Toast 10: BUTTERED
|
||||
Toast 10: JAMMED
|
||||
Chomp! Toast 10: JAMMED
|
||||
Toast 11: DRY
|
||||
Toast 11: BUTTERED
|
||||
Toast 11: JAMMED
|
||||
Chomp! Toast 11: JAMMED
|
||||
Toast 12: DRY
|
||||
Toast 12: BUTTERED
|
||||
Toast 12: JAMMED
|
||||
Chomp! Toast 12: JAMMED
|
||||
Eater interrupted
|
||||
Eater off
|
||||
Jammer interrupted
|
||||
Jammer off
|
||||
Toaster interrupted
|
||||
Butterer interrupted
|
||||
Butterer off
|
||||
Toaster off
|
||||
*/
|
@ -1,230 +0,0 @@
|
||||
// lowlevel/restaurant2/RestaurantWithQueues.java
|
||||
// (c)2017 MindView LLC: see Copyright.txt
|
||||
// We make no guarantees that this code is fit for any purpose.
|
||||
// Visit http://OnJava8.com for more book information.
|
||||
// {java threads.restaurant2.RestaurantWithQueues 5}
|
||||
package threads.restaurant2;
|
||||
import enums.menu.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.*;
|
||||
|
||||
// This is given to the waiter, who gives it to the chef:
|
||||
class Order { // (A data-transfer object)
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
private final Customer customer;
|
||||
private final WaitPerson waitPerson;
|
||||
private final Food food;
|
||||
public Order(Customer cust, WaitPerson wp, Food f) {
|
||||
customer = cust;
|
||||
waitPerson = wp;
|
||||
food = f;
|
||||
}
|
||||
public Food item() { return food; }
|
||||
public Customer getCustomer() { return customer; }
|
||||
public WaitPerson getWaitPerson() { return waitPerson; }
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Order: " + id + " item: " + food +
|
||||
" for: " + customer +
|
||||
" served by: " + waitPerson;
|
||||
}
|
||||
}
|
||||
|
||||
// This comes back from the chef:
|
||||
class Plate {
|
||||
private final Order order;
|
||||
private final Food food;
|
||||
public Plate(Order ord, Food f) {
|
||||
order = ord;
|
||||
food = f;
|
||||
}
|
||||
public Order getOrder() { return order; }
|
||||
public Food getFood() { return food; }
|
||||
@Override
|
||||
public String toString() { return food.toString(); }
|
||||
}
|
||||
|
||||
class Customer implements Runnable {
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
private final WaitPerson waitPerson;
|
||||
// Only one course at a time can be received:
|
||||
private SynchronousQueue<Plate> placeSetting =
|
||||
new SynchronousQueue<>();
|
||||
public Customer(WaitPerson w) { waitPerson = w; }
|
||||
public void
|
||||
deliver(Plate p) throws InterruptedException {
|
||||
// Only blocks if customer is still
|
||||
// eating the previous course:
|
||||
placeSetting.put(p);
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
for(Course course : Course.values()) {
|
||||
Food food = course.randomSelection();
|
||||
try {
|
||||
waitPerson.placeOrder(this, food);
|
||||
// Blocks until course is delivered:
|
||||
System.out.println(
|
||||
this + "eating " + placeSetting.take());
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(this + "waiting for " +
|
||||
course + " interrupted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println(this + "finished meal, leaving");
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Customer " + id + " ";
|
||||
}
|
||||
}
|
||||
|
||||
class WaitPerson implements Runnable {
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
private final Restaurant restaurant;
|
||||
BlockingQueue<Plate> filledOrders =
|
||||
new LinkedBlockingQueue<>();
|
||||
public WaitPerson(Restaurant rest) {
|
||||
restaurant = rest;
|
||||
}
|
||||
public void placeOrder(Customer cust, Food food) {
|
||||
try {
|
||||
// Shouldn't actually block because this is
|
||||
// a LinkedBlockingQueue with no size limit:
|
||||
restaurant.orders.put(new Order(cust, this, food));
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(
|
||||
this + " placeOrder interrupted");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// Blocks until a course is ready
|
||||
Plate plate = filledOrders.take();
|
||||
System.out.println(this + "received " + plate +
|
||||
" delivering to " +
|
||||
plate.getOrder().getCustomer());
|
||||
plate.getOrder().getCustomer().deliver(plate);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(this + " interrupted");
|
||||
}
|
||||
System.out.println(this + " off duty");
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WaitPerson " + id + " ";
|
||||
}
|
||||
}
|
||||
|
||||
class Chef implements Runnable {
|
||||
private static int counter = 0;
|
||||
private final int id = counter++;
|
||||
private final Restaurant restaurant;
|
||||
private static SplittableRandom rand = new SplittableRandom(47);
|
||||
public Chef(Restaurant rest) { restaurant = rest; }
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// Blocks until an order appears:
|
||||
Order order = restaurant.orders.take();
|
||||
Food requestedItem = order.item();
|
||||
// Time to prepare order:
|
||||
TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
|
||||
Plate plate = new Plate(order, requestedItem);
|
||||
order.getWaitPerson().filledOrders.put(plate);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println(this + " interrupted");
|
||||
}
|
||||
System.out.println(this + " off duty");
|
||||
}
|
||||
@Override
|
||||
public String toString() { return "Chef " + id + " "; }
|
||||
}
|
||||
|
||||
class Restaurant implements Runnable {
|
||||
private List<WaitPerson> waitPersons =
|
||||
new ArrayList<>();
|
||||
private List<Chef> chefs = new ArrayList<>();
|
||||
private ExecutorService exec;
|
||||
private static SplittableRandom rand = new SplittableRandom(47);
|
||||
BlockingQueue<Order>
|
||||
orders = new LinkedBlockingQueue<>();
|
||||
public Restaurant(ExecutorService e, int nWaitPersons,
|
||||
int nChefs) {
|
||||
exec = e;
|
||||
for(int i = 0; i < nWaitPersons; i++) {
|
||||
WaitPerson waitPerson = new WaitPerson(this);
|
||||
waitPersons.add(waitPerson);
|
||||
exec.execute(waitPerson);
|
||||
}
|
||||
for(int i = 0; i < nChefs; i++) {
|
||||
Chef chef = new Chef(this);
|
||||
chefs.add(chef);
|
||||
exec.execute(chef);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!Thread.interrupted()) {
|
||||
// A new customer arrives; assign a WaitPerson:
|
||||
WaitPerson wp = waitPersons.get(
|
||||
rand.nextInt(waitPersons.size()));
|
||||
Customer c = new Customer(wp);
|
||||
exec.execute(c);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
System.out.println("Restaurant interrupted");
|
||||
}
|
||||
System.out.println("Restaurant closing");
|
||||
}
|
||||
}
|
||||
|
||||
public class RestaurantWithQueues {
|
||||
public static void
|
||||
main(String[] args) throws Exception {
|
||||
ExecutorService es = Executors.newCachedThreadPool();
|
||||
Restaurant restaurant = new Restaurant(es, 5, 2);
|
||||
es.execute(restaurant);
|
||||
if(args.length > 0) // Optional argument
|
||||
TimeUnit.SECONDS.sleep(new Integer(args[0]));
|
||||
else {
|
||||
System.out.println("Press 'Enter' to quit");
|
||||
System.in.read();
|
||||
}
|
||||
es.shutdownNow();
|
||||
}
|
||||
}
|
||||
/* Output: (First and Last 10 Lines)
|
||||
WaitPerson 0 received SALAD delivering to Customer 0
|
||||
Customer 0 eating SALAD
|
||||
WaitPerson 2 received SPRING_ROLLS delivering to Customer 1
|
||||
Customer 1 eating SPRING_ROLLS
|
||||
WaitPerson 1 received SOUP delivering to Customer 2
|
||||
Customer 2 eating SOUP
|
||||
WaitPerson 0 received LENTILS delivering to Customer 0
|
||||
Customer 0 eating LENTILS
|
||||
WaitPerson 0 received SPRING_ROLLS delivering to Customer 3
|
||||
Customer 3 eating SPRING_ROLLS
|
||||
...________...________...________...________...
|
||||
WaitPerson 2 off duty
|
||||
Customer 33 finished meal, leaving
|
||||
Customer 18 finished meal, leaving
|
||||
Customer 35 finished meal, leaving
|
||||
Customer 46 finished meal, leaving
|
||||
WaitPerson 4 off duty
|
||||
Customer 24 finished meal, leaving
|
||||
Customer 30 finished meal, leaving
|
||||
Customer 34 finished meal, leaving
|
||||
Customer 48 finished meal, leaving
|
||||
*/
|
Loading…
x
Reference in New Issue
Block a user