问题简述:某寺庙有老和尚、小和尚若干。庙内有一水缸,由小和尚提水入缸,供老和尚饮用。水缸可容纳30桶水,每次入水、取水仅为一桶,不可同时进行。水取自同一井中,井口狭窄,每次只能容纳一个水桶取水。设有5只水桶,老和尚与小和尚共用。通过Java给出老和尚和小和尚的活动。
代码实现:采用Java的synchronized关键字和线程池技术来进行实现。不得不说的一点是,对于Java的锁机制,若进行了wait(),notify()和notifyAll()操作,则必须在synchronized块中或声明了synchronized的方法中使用,否则会报出IllegalMonitorStateException异常。若synchronized块中使用了某个对象作为锁,则只能对这个锁进行上述三个操作。例如在本例中采用bucketLock的synchronized块中,使用的notifyAll方法必须采用bucketLock.notifyAll()方法,并且只能对块中的锁进行wait,notifyAll,对于其他的锁,是不能进行这些操作的,否则同样会报IllegalMonitorStateException。要命的是,有些时候,这样的异常可能不会显示出来,在执行notifyAll后直接退出该方法,导致错误很难被发现,因此在使用wait(),notify()和notifyAll()时,一定要注意。
package com.fhp.testthreadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Monk {
public static void main(String[] args) {
final Temple t = new Temple();
ExecutorService youngMonkService = Executors.newFixedThreadPool(50);
ExecutorService oldMonkService = Executors.newFixedThreadPool(50);
for(int i = 0; i < 40; i++) {
youngMonkService.submit(new Runnable() {
@Override
public void run() {
t.YoungMonk(Thread.currentThread().getName());
}
});
oldMonkService.submit(new Runnable() {
@Override
public void run() {
t.OldMonk(Thread.currentThread().getName());
}
});
}
youngMonkService.shutdown();
oldMonkService.shutdown();
}
}
class Temple {
private int bucket = 5;
private int capacity = 30;
private int water = 0;
private Object bucketLock = new Object();
private Object emptyLock = new Object();
private Object fullLock = new Object();
private Object wellLock = new Object();
public void YoungMonk(String id) {
System.out.println("Young monk " + id + ": I am running!");
synchronized(fullLock) {
while(capacity <= 0) {
try {
fullLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
capacity--;
}
System.out.println("Young monk " + id + ": I am trying to get a bucket...");
synchronized(bucketLock) {
while(bucket <= 0) {
try {
System.out.println("Young monk " + id + ": I\'m waiting for a bucket...");
bucketLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
bucket--;
}
System.out.println("Young monk " + id + ": Bucket gotten! " + bucket + " buckets remain.I\'m going to the well...");
synchronized(wellLock) {
System.out.println("Young monk " + id + ": I\'m containing water...");
}
System.out.println("Young monk " + id + ": Going back to the temple...");
synchronized(bucketLock) {
bucket++;
System.out.println("Young monk " + id + ": Recent bucket:" + bucket);
bucketLock.notifyAll();
}
synchronized(emptyLock) {
water++;
// capacity--;
System.out.println("Young monk " + id + ": Recent water:" + water);
emptyLock.notifyAll();
}
System.out.println("Young monk " + id + " is quitting! Recent capacity:" + capacity);
}
public void OldMonk(String id) {
System.out.println("Old monk " + id + ": I am running!");
synchronized(emptyLock) {
while(capacity >= 30) {
try {
emptyLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
capacity++;
}
System.out.println("Old monk " + id + ": I am trying to get a bucket...");
synchronized(bucketLock) {
while(bucket <= 0) {
try {
System.out.println("Old monk " + id + ": I\'m waiting for a bucket...");
bucketLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
bucket--;
}
System.out.println("Old monk " + id + ": Bucket gotten! " + bucket + " buckets remain.I\'m going to the jar...");
synchronized(bucketLock) {
bucket++;
System.out.println("Old monk " + id + ": Recent bucket:" + bucket);
bucketLock.notifyAll();
}
synchronized(fullLock) {
water--;
// capacity++;
System.out.println("Old monk " + id + ": Recent water:" + water);
fullLock.notifyAll();
}
System.out.println("Old monk " + id + " is quitting! Recent capacity:" + capacity);
}
}
运行结果(由于篇幅过长,这里使用在main函数的for循环中i=5的情况):
Young monk pool-1-thread-1: I am running!
Young monk pool-1-thread-1: I am trying to get a bucket...
Young monk pool-1-thread-1: Bucket gotten! 4 buckets remain.I'm going to the well...
Young monk pool-1-thread-1: I'm containing water...
Young monk pool-1-thread-1: Going back to the temple...
Young monk pool-1-thread-1: Recent bucket:5
Young monk pool-1-thread-1: Recent water:1
Young monk pool-1-thread-1 is quitting! Recent capacity:29
Old monk pool-2-thread-1: I am running!
Old monk pool-2-thread-1: I am trying to get a bucket...
Old monk pool-2-thread-1: Bucket gotten! 4 buckets remain.I'm going to the jar...
Old monk pool-2-thread-1: Recent bucket:5
Old monk pool-2-thread-1: Recent water:0
Old monk pool-2-thread-1 is quitting! Recent capacity:30
Young monk pool-1-thread-2: I am running!
Young monk pool-1-thread-2: I am trying to get a bucket...
Young monk pool-1-thread-2: Bucket gotten! 4 buckets remain.I'm going to the well...
Young monk pool-1-thread-2: I'm containing water...
Old monk pool-2-thread-2: I am running!
Young monk pool-1-thread-2: Going back to the temple...
Young monk pool-1-thread-3: I am running!
Young monk pool-1-thread-3: I am trying to get a bucket...
Old monk pool-2-thread-3: I am running!
Young monk pool-1-thread-2: Recent bucket:5
Young monk pool-1-thread-3: Bucket gotten! 4 buckets remain.I'm going to the well...
Young monk pool-1-thread-3: I'm containing water...
Young monk pool-1-thread-3: Going back to the temple...
Young monk pool-1-thread-3: Recent bucket:5
Young monk pool-1-thread-3: Recent water:1
Young monk pool-1-thread-3 is quitting! Recent capacity:29
Young monk pool-1-thread-2: Recent water:2
Young monk pool-1-thread-2 is quitting! Recent capacity:28
Old monk pool-2-thread-3: I am trying to get a bucket...
Old monk pool-2-thread-3: Bucket gotten! 4 buckets remain.I'm going to the jar...
Old monk pool-2-thread-2: I am trying to get a bucket...
Old monk pool-2-thread-3: Recent bucket:5
Old monk pool-2-thread-3: Recent water:1
Old monk pool-2-thread-3 is quitting! Recent capacity:29
Old monk pool-2-thread-2: Bucket gotten! 4 buckets remain.I'm going to the jar...
Old monk pool-2-thread-2: Recent bucket:5
Old monk pool-2-thread-2: Recent water:0
Old monk pool-2-thread-2 is quitting! Recent capacity:30
Young monk pool-1-thread-4: I am running!
Young monk pool-1-thread-4: I am trying to get a bucket...
Old monk pool-2-thread-4: I am running!
Young monk pool-1-thread-4: Bucket gotten! 4 buckets remain.I'm going to the well...
Young monk pool-1-thread-4: I'm containing water...
Young monk pool-1-thread-5: I am running!
Young monk pool-1-thread-5: I am trying to get a bucket...
Young monk pool-1-thread-4: Going back to the temple...
Young monk pool-1-thread-4: Recent bucket:4
Young monk pool-1-thread-5: Bucket gotten! 3 buckets remain.I'm going to the well...
Young monk pool-1-thread-5: I'm containing water...
Young monk pool-1-thread-5: Going back to the temple...
Old monk pool-2-thread-5: I am running!
Young monk pool-1-thread-5: Recent bucket:5
Young monk pool-1-thread-5: Recent water:1
Young monk pool-1-thread-5 is quitting! Recent capacity:29
Old monk pool-2-thread-4: I am trying to get a bucket...
Old monk pool-2-thread-4: Bucket gotten! 4 buckets remain.I'm going to the jar...
Old monk pool-2-thread-4: Recent bucket:5
Old monk pool-2-thread-4: Recent water:1
Old monk pool-2-thread-4 is quitting! Recent capacity:29
Old monk pool-2-thread-5: I am trying to get a bucket...
Old monk pool-2-thread-5: Bucket gotten! 4 buckets remain.I'm going to the jar...
Old monk pool-2-thread-5: Recent bucket:5
Old monk pool-2-thread-5: Recent water:0
Old monk pool-2-thread-5 is quitting! Recent capacity:30
Young monk pool-1-thread-4: Recent water:2
Young monk pool-1-thread-4 is quitting! Recent capacity:30