Created
September 7, 2016 06:23
-
-
Save markselby9/a00603b3cab0f4f042a8a8776a389d72 to your computer and use it in GitHub Desktop.
Producer Consumer problem, with a buffer whose max size is 10. The chef and waiter start working with random time needed each time, so randomly the buffer would be full or empty at some time.
This file contains 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.ArrayList; | |
import java.util.Random; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.TimeUnit; | |
import static java.lang.Thread.sleep; | |
/** | |
* Created by fengchaoyi on 16/9/6. | |
*/ | |
//Thinking in Java P703 | |
public class ProducerConsumerProblemWithBuffer { | |
public static void main(String[] args) { | |
new Restaurant(); | |
} | |
} | |
class Restaurant { | |
private ArrayList<Meal> mealArrayList = new ArrayList<Meal>(); | |
private int mealBufferMaxSize = 10; // set the buffer size as 10 | |
Waiter waiter; | |
Chef chef; | |
ExecutorService executorService = Executors.newCachedThreadPool(); | |
Restaurant() { | |
this.mealArrayList = new ArrayList<Meal>(); | |
this.waiter = new Waiter(this); | |
this.chef = new Chef(this); | |
executorService.execute(chef); | |
try { | |
sleep(100); //chef work first | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
executorService.execute(waiter); | |
} | |
boolean bufferFull() { | |
return mealArrayList.size() == mealBufferMaxSize; | |
} | |
boolean bufferEmpty() { | |
return mealArrayList.size() == 0; | |
} | |
Meal popMeal() { | |
return mealArrayList.remove(0); | |
} | |
void addMeal(Meal meal) { | |
mealArrayList.add(meal); | |
} | |
} | |
class Waiter implements Runnable { | |
private Restaurant restaurant; | |
Waiter(Restaurant restaurant) { | |
this.restaurant = restaurant; | |
this.restaurant.waiter = this; | |
} | |
@Override | |
public void run() { | |
try { | |
while (!Thread.interrupted()) { | |
synchronized (this) { | |
if (restaurant.bufferEmpty()) { | |
System.out.println("Buffer empty, wait for chef."); | |
wait(); // wait for chef's notifyAll() | |
} | |
} | |
Meal nextMeal = restaurant.popMeal(); | |
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(100)); | |
nextMeal.process(); | |
synchronized (restaurant.chef) { | |
restaurant.chef.notifyAll(); | |
} | |
} | |
} catch (InterruptedException e) { | |
System.out.println("ProducerConsumer1.Waiter interrupted"); | |
} | |
} | |
} | |
class Chef implements Runnable { | |
private Restaurant restaurant; | |
private int count; | |
private int materialCount = 100; | |
Chef(Restaurant restaurant) { | |
this.restaurant = restaurant; | |
this.restaurant.chef = this; | |
this.count = 0; | |
} | |
@Override | |
public void run() { | |
try { | |
while (!Thread.interrupted()) { | |
synchronized (this) { | |
// // this lock of chef is automatically released, so that waiter.notifyAll() can catch this lock | |
if (restaurant.bufferFull()) { | |
System.out.println("Buffer is full, wait for waiter."); | |
wait(); | |
} | |
} | |
this.count += 1; | |
if (this.count > this.materialCount) { | |
System.out.println("Running out of material. Closing..."); | |
restaurant.executorService.shutdownNow();//not shutdown() | |
} | |
Meal newMeal = new Meal(this.count); | |
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(100)); | |
restaurant.addMeal(newMeal); | |
synchronized (restaurant.waiter) { | |
System.out.println("notifyAll waiter for meal " + count + " ready."); | |
restaurant.waiter.notifyAll(); | |
} | |
} | |
} catch (InterruptedException e) { | |
System.out.println("ProducerConsumer1.Chef interrupted"); | |
} | |
} | |
} | |
class Meal { | |
private int number; | |
Meal(int number) { | |
this.number = number; | |
} | |
void process() { | |
System.out.println("ProducerConsumer1.Meal " + this.number + " is being given to customer!"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment