2016-07-05 14:46:09 -06:00
|
|
|
// threads/restaurant2/RestaurantWithQueues.java
|
2015-12-15 11:47:04 -08:00
|
|
|
// (c)2016 MindView LLC: see Copyright.txt
|
2015-11-15 15:51:35 -08:00
|
|
|
// We make no guarantees that this code is fit for any purpose.
|
2016-09-23 13:23:35 -06:00
|
|
|
// Visit http://OnJava8.com for more book information.
|
2016-07-28 12:48:23 -06:00
|
|
|
// {java threads.restaurant2.RestaurantWithQueues 5}
|
2016-07-05 14:46:09 -06:00
|
|
|
package threads.restaurant2;
|
2015-06-15 17:47:35 -07:00
|
|
|
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 is what 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:
|
2015-12-02 09:20:27 -08:00
|
|
|
System.out.println(
|
|
|
|
this + "eating " + placeSetting.take());
|
2015-06-15 17:47:35 -07:00
|
|
|
} catch(InterruptedException e) {
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + "waiting for " +
|
2015-06-15 17:47:35 -07:00
|
|
|
course + " interrupted");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + "finished meal, leaving");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
|
|
|
@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<>();
|
2016-01-25 18:05:55 -08:00
|
|
|
public WaitPerson(Restaurant rest) {
|
|
|
|
restaurant = rest;
|
|
|
|
}
|
2015-06-15 17:47:35 -07:00
|
|
|
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) {
|
2016-01-25 18:05:55 -08:00
|
|
|
System.out.println(
|
|
|
|
this + " placeOrder interrupted");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
while(!Thread.interrupted()) {
|
|
|
|
// Blocks until a course is ready
|
|
|
|
Plate plate = filledOrders.take();
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + "received " + plate +
|
2015-06-15 17:47:35 -07:00
|
|
|
" delivering to " +
|
|
|
|
plate.getOrder().getCustomer());
|
|
|
|
plate.getOrder().getCustomer().deliver(plate);
|
|
|
|
}
|
|
|
|
} catch(InterruptedException e) {
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + " interrupted");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + " off duty");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
|
|
|
@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;
|
2016-01-25 18:05:55 -08:00
|
|
|
private static SplittableRandom rand = new SplittableRandom(47);
|
2015-06-15 17:47:35 -07:00
|
|
|
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) {
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + " interrupted");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println(this + " off duty");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
|
|
|
@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;
|
2016-01-25 18:05:55 -08:00
|
|
|
private static SplittableRandom rand = new SplittableRandom(47);
|
2015-06-15 17:47:35 -07:00
|
|
|
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) {
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println("Restaurant interrupted");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println("Restaurant closing");
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class RestaurantWithQueues {
|
2016-01-25 18:05:55 -08:00
|
|
|
public static void
|
|
|
|
main(String[] args) throws Exception {
|
|
|
|
ExecutorService es = Executors.newCachedThreadPool();
|
|
|
|
Restaurant restaurant = new Restaurant(es, 5, 2);
|
|
|
|
es.execute(restaurant);
|
2015-06-15 17:47:35 -07:00
|
|
|
if(args.length > 0) // Optional argument
|
|
|
|
TimeUnit.SECONDS.sleep(new Integer(args[0]));
|
|
|
|
else {
|
2015-11-03 12:00:44 -08:00
|
|
|
System.out.println("Press 'Enter' to quit");
|
2015-06-15 17:47:35 -07:00
|
|
|
System.in.read();
|
|
|
|
}
|
2016-01-25 18:05:55 -08:00
|
|
|
es.shutdownNow();
|
2015-06-15 17:47:35 -07:00
|
|
|
}
|
2015-09-07 11:44:36 -06:00
|
|
|
}
|
2016-07-20 06:32:39 -06:00
|
|
|
/* Output: (First and Last 10 Lines)
|
2016-07-22 14:45:35 -06:00
|
|
|
WaitPerson 0 received SALAD delivering to Customer 0
|
|
|
|
Customer 0 eating SALAD
|
|
|
|
WaitPerson 2 received SPRING_ROLLS delivering to Customer 1
|
2015-06-15 17:47:35 -07:00
|
|
|
Customer 1 eating SPRING_ROLLS
|
2016-07-22 14:45:35 -06:00
|
|
|
WaitPerson 1 received SOUP delivering to Customer 2
|
2015-06-15 17:47:35 -07:00
|
|
|
Customer 2 eating SOUP
|
2016-07-22 14:45:35 -06:00
|
|
|
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
|
|
|
|
...________...________...________...________...
|
2016-07-27 11:12:11 -06:00
|
|
|
WaitPerson 2 off duty
|
|
|
|
Customer 33 finished meal, leaving
|
|
|
|
Customer 18 finished meal, leaving
|
|
|
|
Customer 35 finished meal, leaving
|
2016-07-22 14:45:35 -06:00
|
|
|
Customer 46 finished meal, leaving
|
2016-07-27 11:12:11 -06:00
|
|
|
WaitPerson 4 off duty
|
|
|
|
Customer 24 finished meal, leaving
|
|
|
|
Customer 30 finished meal, leaving
|
|
|
|
Customer 34 finished meal, leaving
|
|
|
|
Customer 48 finished meal, leaving
|
2015-09-07 11:44:36 -06:00
|
|
|
*/
|