熟睡的理发师问题

        熟睡的理发师问题中,一个理发师对应n个顾客的问题,该理发店只能容纳n个顾客,当没有顾客的时候,理发师就会睡觉;当顾客来了,理发师就会醒过来。对于顾客而言,当来到理发店,若理发师睡着了,则叫醒理发师,如果店里人满了,则离开,如果人没满,但理发师在忙,则进行等待。在这个过程中,有几点需要注意的,首先是假定人是按一定顺序进来的,而不是一蜂窝进来,那么需要保证人进来的过程是同步的,本文示例体现在对几个状态的判断函数都是同步的,以及对人数的加减都是同步或者线程安全的。其次就是理发的问题,这里理发只能有一个人进行理发,因此使用信号量Semaphore来控制理发的许可,即获得许可的则可以进行理发,而其他人只能等当前这个人理完发付完钱(即释放许可)才能获取这个许可。这样能够将理发以及顾客进出独立开来。具体代码如下所示:

import java.util.concurrent.Semaphore;
public class BarberShop {
	static int max_seat=7;
	static int cur_cm=0;
	static boolean onBusy=false;
	static boolean onSleep=true;
	static Semaphore sem=new Semaphore(1);
	class Customer{
		
		private synchronized boolean isFull()
		{
			if(cur_cm==max_seat)
				return true;
			return false;
		}
		private synchronized boolean isBusy()
		{
			if(onBusy)
				return true;
			return false;
		}
		private synchronized boolean isSleep() {
			if(onSleep)
				return true;
			return false;
		}
		
		public void  solve(int index) throws InterruptedException
		{
			System.out.println("顾客"+index+"来了");
			if(isFull()) {
				System.out.println("由于现在没有位子了,顾客"+index+"离开了");
			}
			else {
				synchronized(this)
				{
					cur_cm++;
				}
				if(isBusy())
				{
					System.out.println("现在理发师正在理发,找个位置等等,当前共有"+(cur_cm)+"人");
				}
				sem.acquire();//获取信号量,防止其他线程进入,就是该顾客获取了理发的许可,其它顾客则继续等待。
				
				if(cur_cm==1)
				{
					if(isSleep())
					{
						System.out.println("现在顾客"+index+"来了,理发师被叫醒");
						onSleep=false;
					}
				}
				onBusy=true;
				System.out.println("顾客"+index+"正在理发");
				Thread.sleep(1000);//理发时间
				cur_cm--;
				System.out.println("顾客"+index+"理完头发离开了"+",当前共有"+cur_cm+"人");
				onBusy=false;
				if(cur_cm==0)
				{
					System.out.println("没有顾客了,理发师开始睡觉!");
					onSleep=true;
				}
				sem.release();//释放信号量,给下一个顾客获取许可。
				
			}
			
		}
		
	}
	class Barber extends Thread{
		
		/**
		 * 需要有一个值来判断理发师是否在忙,还需要一个值来记录理发店的人;
		 */
		private Customer cm;
		private int index;
		public Barber(Customer cm,int index)
		{
			this.cm=cm;
			this.index=index;
		}
		public void run()
		{
			try {
				cm.solve(index);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args)throws InterruptedException {
		// TODO Auto-generated method stub
		BarberShop bs=new BarberShop();
		Customer cm=bs.new Customer();
		for(int i=0;i<20;i++)
		{
			bs.new Barber(cm,i).start();
			Thread.sleep((int)(400-Math.random()*300));
		}

	}

}

运行结果如下:

顾客0来了
现在顾客0来了,理发师被叫醒
顾客0正在理发
顾客1来了
现在理发师正在理发,找个位置等等,当前共有2人
顾客2来了
现在理发师正在理发,找个位置等等,当前共有3人
顾客3来了
现在理发师正在理发,找个位置等等,当前共有4人
顾客4来了
现在理发师正在理发,找个位置等等,当前共有5人
顾客0理完头发离开了,当前共有4人
顾客1正在理发
顾客5来了
现在理发师正在理发,找个位置等等,当前共有5人
顾客6来了
现在理发师正在理发,找个位置等等,当前共有6人
顾客7来了
现在理发师正在理发,找个位置等等,当前共有7人
顾客8来了
由于现在没有位子了,顾客8离开了
顾客1理完头发离开了,当前共有6人
顾客2正在理发
顾客9来了
现在理发师正在理发,找个位置等等,当前共有7人
顾客10来了
由于现在没有位子了,顾客10离开了
顾客11来了
由于现在没有位子了,顾客11离开了
顾客12来了
由于现在没有位子了,顾客12离开了
顾客13来了
由于现在没有位子了,顾客13离开了
顾客14来了
由于现在没有位子了,顾客14离开了
顾客2理完头发离开了,当前共有6人
顾客3正在理发
顾客15来了
现在理发师正在理发,找个位置等等,当前共有7人
顾客16来了
由于现在没有位子了,顾客16离开了
顾客17来了
由于现在没有位子了,顾客17离开了
顾客3理完头发离开了,当前共有6人
顾客4正在理发
顾客18来了
现在理发师正在理发,找个位置等等,当前共有7人
顾客19来了
由于现在没有位子了,顾客19离开了
顾客4理完头发离开了,当前共有6人
顾客5正在理发
顾客5理完头发离开了,当前共有5人
顾客6正在理发
顾客6理完头发离开了,当前共有4人
顾客7正在理发
顾客7理完头发离开了,当前共有3人
顾客9正在理发
顾客9理完头发离开了,当前共有2人
顾客15正在理发
顾客15理完头发离开了,当前共有1人
顾客18正在理发
顾客18理完头发离开了,当前共有0人
没有顾客了,理发师开始睡觉!
         以上通过Semaphore来控制理发的许可,使得理发师理发,以及顾客进出是两个独立的事件,顾客进出使用synchronized加以控制,而理发则通过信号量来控制,从而使得整个理发店的工作不会出错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值