用信号量机制实现吃冰淇淋问题:桌子上有一只盘子,最多可容纳两个冰淇淋,每次只能放入或者取出一个冰淇淋。男厨师专门向盘子中放巧克力冰淇淋,女厨师专门向盘子中放抹茶冰淇淋,两个男顾客专门等待吃盘子中的巧克力冰淇淋,两个女顾客专门等吃盘子中的抹茶冰淇淋(JAVA代码实现)
具体代码实现如下
package SemIceCream01;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemIce01 {
private static final int PLATE = 1;//一个盘子
private static final int EMPTY = 2;//空缓冲区数量,初始为2
private static final int FULL = 0;//满缓冲区数量,初始为0
private static final int ICE_CHOCOLATE = 0;//巧克力冰淇淋个数,初始为0
private static final int ICE_MATCHA = 0;//抹茶冰淇淋个数,初始为0
//多线程共享的可操作数据,可视为临界资源
static int ic=0;//巧克力冰淇淋
static int im=0;//抹茶冰淇淋
public static void main(String[] args) {
//创建信号量
Semaphore plate=new Semaphore(PLATE);
Semaphore empty=new Semaphore(EMPTY);
Semaphore full=new Semaphore(FULL);
Semaphore iceChocolate=new Semaphore(ICE_CHOCOLATE);
Semaphore iceMatcha=new Semaphore(ICE_MATCHA);
//创建线程池
ExecutorService ThreadPool = Executors.newFixedThreadPool(6);
//在线程池中执行任务
ThreadPool.execute(new CookThread(plate, full, empty, iceChocolate, 1));
ThreadPool.execute(new CookThread(plate, full, empty, iceMatcha, 2));
ThreadPool.execute(new CustomerThread(plate, full, empty, iceChocolate, 1));
ThreadPool.execute(new CustomerThread(plate, full, empty, iceChocolate, 2));
ThreadPool.execute(new CustomerThread(plate, full, empty, iceMatcha, 3));
ThreadPool.execute(new CustomerThread(plate, full, empty, iceMatcha, 4));
//关闭线程池
ThreadPool.shutdown();
}
}
class CookThread extends Thread{
// 信号量
private volatile Semaphore plate;
private volatile Semaphore full;
private volatile Semaphore empty;
private volatile Semaphore chocolate;
//几号厨师
private int i;
public CookThread(Semaphore plate,Semaphore full,Semaphore empty,Semaphore Chocolate,int i) {
this.plate=plate;
this.full=full;
this.empty=empty;
this.chocolate=Chocolate;
this.i=i;
}
@Override
public void run() {
while(true) {
try {
empty.acquire();//根据判断有无容量决定是否继续后面的工作
/*若不加这行,也就意味着两个厨师可同时放冰淇淋,或在厨师放的同时,顾客吃等*/
plate.acquire(); //P操作,信号量-1
if(i==1){
SemIce01.ic++;
System.out.println("男厨师向盘子中放入巧克力冰淇淋,\t当前有"+(SemIce01.ic+SemIce01.im)+
"个冰淇淋,\t其中巧克力冰淇淋有"+SemIce01.ic+"个,\t抹茶冰淇淋有"
+SemIce01.im+"个");
}
if(i==2) {
SemIce01.im++;
System.out.println("女厨师向盘子中放入抹茶冰淇淋,\t当前有"+(SemIce01.ic+SemIce01.im)+
"个冰淇淋,\t其中巧克力冰淇淋有"+SemIce01.ic+
"个,\t抹茶冰淇淋有"+SemIce01.im+"个");
}
//Thread.sleep(2000);采用随机数效果是否更好
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}finally {
plate.release();//V操作,信号量+1
full.release();//信号量+1
chocolate.release();
}
}
}
}
class CustomerThread extends Thread{
// 信号量
private volatile Semaphore plate;
private volatile Semaphore full;
private volatile Semaphore empty;
private volatile Semaphore chocolate;
//几号顾客
private int i;
public CustomerThread(Semaphore plate,Semaphore full,Semaphore empty,Semaphore Chocolate,int i) {
this.plate=plate;
this.full=full;
this.empty=empty;
this.chocolate=Chocolate;
this.i=i;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
try {
full.acquire();//根据是否有满缓冲区决定是进行后面的工作还是等待
chocolate.acquire();//根据是否有对应的冰淇淋决定是进行后面的工作还是等待
plate.acquire();
if(i<3) {
SemIce01.ic--;
System.out.println("男顾客"+i+"号吃掉一个巧克力冰淇淋,\t"
+ "当前有"+(SemIce01.ic+SemIce01.im)+"个冰淇淋,\t其中巧克力冰淇淋有"
+SemIce01.ic+"个,\t抹茶冰淇淋有"+SemIce01.im+"个");
}
else {
SemIce01.im--;
System.out.println("女顾客"+(i-2)+"号吃掉一个抹茶冰淇淋,\t当前有"+
(SemIce01.ic+SemIce01.im)+"个冰淇淋,\t其中巧克力冰淇淋有"+
SemIce01.ic+"个,\t抹茶冰淇淋有"+SemIce01.im+"个");
}
//Thread.sleep(2000);采用随机数效果是否更好
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}finally {
plate.release();
empty.release();
}
}
}
}
参考如下:
《计算机操作系统》(第四版)p53 2.4.3信号量机制 p60 2.5.1.1利用记录型信号量解决生产者-消费者问题