用信号量机制实现吃冰淇淋问题:桌子上有一只盘子,最多可容纳两个冰淇淋,每次只能放入或者取出一个冰淇淋。男厨师专门向盘子中放巧克力冰淇淋,女厨师专门向盘子中放抹茶冰淇淋,两个男顾客专门等待吃盘子中的巧克力冰淇淋,两个女顾客专门等吃盘子中的抹茶冰淇淋(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利用记录型信号量解决生产者-消费者问题