其他分享
首页 > 其他分享> > 设计三:哲学家进餐问题

设计三:哲学家进餐问题

作者:互联网

设计目的:
死锁是进程并发执行过程中可能出现的现象,哲学家就餐问题是描述死锁的经典例子。通过实现哲学家进餐问题的同步,深入了解和掌握进程同步和互斥的原理。
设计内容:模拟有五个哲学家的哲学家进餐问题。
问题描述:5个哲学家同坐在一张圆桌旁,每个人的面前摆放着碗,碗的两旁各摆放着一只筷子。假设哲学家的生活除了吃饭就是思考问题(这是一种抽象,即对该问题而言其他活动都无关紧要),而吃饭的时候需要左手拿一只筷子,右手拿一只筷子,然后开始进餐。吃完后又将筷子放回原处,继续思考问题。设计一个程序,能够显示当前各哲学家的状态和桌上餐具的使用情况,并能无死锁的推算出下一状态各哲学家的状态和桌上餐具的使用情况。即设计一个能安排哲学家正常生活的程序。
为哲学家设计3种状态,即“等待”“进餐”“思考”。每个哲学家重复进行“等待”->“进餐”->“思考”的行动循环。
“等待”->“进餐”:只有一个哲学家处于等待进餐状态,且左右手两边的筷子都处于“空闲”状态时,可以发生这种状态改变。此状态改变发生后,哲学家拿起左右手两边的筷子。
“进餐”->“思考”:此状态改变发生后,哲学家放下左右手上的筷子。筷子状态由“使用中”转变为“空闲”
 “思考”->“等待”:哲学家思考结束后,无条件转入等待状态。
原理C:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号的哲学家则相反。按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子。即五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,跟FIFO原则,则先申请的哲学家会较先可以吃饭,因此不会出现饿死的哲学家。

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;

public class Main {

	/**
	 * @param args
	 */
	static Semaphore chopsticks[] = new Semaphore[5];//创建一个信号量大小为5的数组,模拟五根筷子

	static class TakeRunnable implements Runnable{
		private int i=0;
		
		public TakeRunnable(int i) {
			this.i = i;
		}
		
		public void think(){
			System.out.println("第"+(i+1)+"号哲学家在思考");
		}
		
		public void eat(){
			System.out.println("第"+(i+1)+"号哲学家在进餐");
		}
		/*Runnable接口中有个abstract类型的run方法需要实现,将实现进餐的
		功能写在run方法内*/
		public void run()
		{
			while(true)
			{
				
			try{
				if((i+1)%2!=0)
				{
					chopsticks[i].acquire();
					chopsticks[(i+1)%5].acquire();
				}
				else
				{
					chopsticks[(i+1)%5].acquire();
					chopsticks[i].acquire();
				}
				eat();
				if((i+1)%2!=0)
				{
					chopsticks[i].release();
					chopsticks[(i+1)%5].release();
				}
				else
				{
					chopsticks[(i+1)%5].release();
					chopsticks[i].release();
				}
				think();
				Thread.sleep(1000);
			}catch (Exception e) {
				// TODO: handle exception
				 e.printStackTrace();
			}
			}
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService philosopher =Executors.newFixedThreadPool(5);/*创建一个大小为5的定长线程池
		,控制线程的最大并发数,超出的线程会在队列中等待*/
		for(int i=0;i<chopsticks.length;i++)
		{
			chopsticks[i]=new Semaphore(1,true);/*初始化可用的许可数目为1,保证信号量在被征用
			的时候按照先进先出算法的顺序执行*/
		}
		for(int i=0;i<5;i++)
		{
			philosopher.execute(new TakeRunnable(i));//创建5个哲学家线程,传入TakeRunnable方法实现哲学家的就餐
		}
	}
	
}

标签:状态,进餐,哲学家,chopsticks,筷子,设计,public
来源: https://blog.csdn.net/weixin_44468506/article/details/93349289