1. Meal Class
Class Meal {
private final int ordernum;
Public Meal (int ordernum) {
this.ordernum = ordernum;
}
Public String toString () {return
"Meal" + Ordernum
}
}
2. Chef Class
Class Chef implements Runnable {private restaurant restaurant;
private int count = 0;
Public Chef (Restaurant r) {restaurant = R; public void Run () {try {) ' while '! Thread.interrupted ()) {synchronized (this) {//is likely to jump to another thread//habitual
The usage ensures that you can return to the wait state while (restaurant.meal!= null)//May jump to another thread at this time Wait ();
Meal to is taken}//unblock blocking state execution if (++count = 10) {
Print ("Out of food, closing");
Thread internal restaurant.exec.shutdownNow ();
} PRINTNB ("Order up!"); A call to Notifyall () must first capture the lock on the Waitperson//because the call to Notifyall () necessarily owns the lock//This ensures that two attempts to invoke the same object on the same objects Notifyal
L () tasks do not conflict with each other//when executed here, if you need to wait for the lock then the thread will switch to chef so it can continue to run Synchronized (Restaurant.waitperson) {//Modify the state of the time must obtain the Waitperson lock, otherwise in the modified state if the thread has switched,
The deadlock restaurant.meal = new Meal (count) is caused by a missing signal (such as a notifyall and then a thread switching to wait);
At this point, the Restaurant.waitPerson.notifyAll () can be executed regardless of the Waitperson/blocking state of the block.
}//This time may jump to another thread to make the chef thread in a blocking/non-blocking state TimeUnit.MILLISECONDS.sleep (100);
} catch (Interruptedexception e) {print ("Chef interrupted");
}
}
}
3. Waitperson class
Class Waitperson implements Runnable {
Private restaurant restaurant;
Public Waitperson (Restaurant R) {
restaurant = R;
}
public void Run () {
try {a while
! Thread.interrupted ()) {
synchronized (this) {while
(restaurant.meal = null) wait
()///... for the chef to Produce a meal
}
print ("Waitperson got" + restaurant.meal);
Synchronized (restaurant.chef) {
restaurant.meal = null;
Restaurant.chef.notifyAll (); Ready for another
}
\
catch (Interruptedexception e) {
print ("Waitperson interrupted");
}
}
}
4. Restaurant class
Restaurant is the focus of Waitperson and chef, and they all have to know which restaurant work for,
//because they have to deal with the restaurant's "window" to place or take a meal restaurant.meal.
public class Restaurant {
//Meal Meal Meal of the dining window
;
Executorservice exec = Executors.newcachedthreadpool ();
Waitperson Waitperson = new Waitperson (this);
Chef Chef = new Chef (this);
Starts two threads public
restaurant () {
Exec.execute (chef) in the construction method;
Exec.execute (Waitperson);
}
public static void Main (string[] args) {
new restaurant ();
}
}
Class diagram
Execution process:
After starting the chef thread,
First get the self lock. At this point, the thread scheduler may jump to another thread, which should be considered when using synchronized to synchronize code blocks.
(may be in the state of getting to the chef lock, or it may be in the state of releasing the chef lock after being suspended)
while (! Thread.interrupted ()) {
//First Get Chef Object lock
//Determine if you want to suspend this thread
//Suspend thread form a task in the chef lock waiting condition
//Whether or not to suspend this thread Release this thread object lock
synchronized (this) {
////may jump to another thread
//idiom to ensure that you can return to the wait state while
(restaurant.meal!= null)
////This time may jump to another thread wait
()///... for the meal to be taken
}
1. The thread scheduler executes the Waitperson thread when it is in the state of acquiring the chef lock
Because of Meal==null, the Waitperson thread hangs, releasing the Waitperson lock
2. The thread scheduler executes the Waitperson thread when it is in the state of releasing the chef lock
Because of Meal==null, the Waitperson thread hangs, releasing the Waitperson lock
So the same way, or to go back to the chef thread, continue to execute
After performing the Domeal action
First obtain Waitperson lock, Waitperson Lock does not exist locked situation. Exist. For example, when executing a waitperson thread, the thread scheduler switches the thread when it has just entered the synchronized (this) synchronized code block, at which point the Waitperson Lock is acquired by the Waitperson thread. Then the chef thread is blocked, the thread scheduler switches the thread, the Waitperson thread continues execution, the lock is released, and the thread hangs. The chef thread can continue to execute. Get the Waitperson lock, modify the state (when modifying the state must obtain Waitperson lock, otherwise in the modified state if the thread has switched, it will cause missed signals (such as the first notifyall and then the thread switch to wait) caused by the deadlock). Notifies the Waitperson thread to release the Waitperson lock. At this point, the Waitperson can continue to run regardless of whether it is in a non-blocking or suspended state, and the Waitperson switch is either suspended or non-blocking at this point.
By reading this program, you will find that the idea is not so clear. Before doing Waxonwaxoff code reading, the two procedures in the idea of what is different.
1. The Waxonwaxoff program is a repeated two-thread operation on an object car, using a lock on the object. The Chefwaitperson program is a single producer consumer task that uses two thread object locks and is more complex.
2. Note that in the Chefwaitperson program its thread scheduler can switch threads at any of the program's statements (the Synchronized keyword does not prevent the thread from switching, but can only guarantee that it acquires the lock to execute in a multitasking order). Therefore, in many cases, switching can still ensure that two threads do not deadlock situation, its state management is not waxonwaxoff simple and clear.