多线程解决哲学家就餐问题(Java)

多线程解决哲学家就餐问题(Java)

       哲学家就餐问题是计算机科学中的一个经典问题,用于演示在并行计算中多线程同步时产生的问题。
题目要求:
        五位哲学家围着一张桌子而坐,他们不交谈,每人面前放了一碗饭,每个人之间放了一只筷子(总共5只筷子)。哲学家只能做两件事, 吃饭和思考,吃饭时不思考,思考时不吃饭。哲学家只能拿起自己身边的两只筷子才能吃饭,拿筷子的顺序是先拿左手再拿右手(不同时)。

题目分析:
  因为哲学家之间不会交谈故可能会发生很严重的情况:
      1.发生死锁,即每个哲学家都是左手拿着筷子,等待着右侧的筷子空闲,这就发生了死锁,谁也吃不了饭。
       2.出现他们同时左手拿起筷子,又同时放下左手的筷子,循环往复。
       3.不加锁则会出现五个人同时吃饭的情况。

解题流程:
      首先判断左右手是否同时有空闲的筷子,如果没有,就持续思考,如果有,则先取左手筷子再取右手筷子,然后停止思考并吃饭,吃完饭后清洗筷子放到桌面上并继续思考,此时处于吃饱状态,不会再重复吃饭。

public class Test {

	public static void main(String[] args) {
		Object obj = new Object();
		boolean[] chopsticks= {false,false,false,false,false};//每位哲学家的筷子初始状态
		for (int i = 0; i<5; i++) {
			//创建线程
			Philosophy phi = new Philosophy(i, false, false, true, true);
			phi.setObj(obj);//带锁
			phi.setChopsticks(chopsticks);//传筷子
			phi.start();//启动线程
		}
	}

}

class Philosophy extends Thread{
	//筷子状态
	boolean[] chopsticks; //true 拿起    false  放下
	//哲学家编号
	private int i;
	//左手
	private Boolean leftFlag = false;//true 拿起    false  放下
	//右手
	private Boolean rightFlag = false;//true 拿起    false  放下
	//饥饿状态
	private Boolean hungry = true;//true 饥饿    false  已经吃完饭
	//思考状态
	private Boolean thinkFlag = false;//true 思考中    false 未思考

	private Object obj;//锁

	//有参构造
	public Philosophy(int i, Boolean leftFlag, Boolean rightFlag, Boolean hungry,
			Boolean thinkFlag) {
		this.i = i;
		this.leftFlag = leftFlag;
		this.rightFlag = rightFlag;
		this.hungry = hungry;
		this.thinkFlag = thinkFlag;
	}

	//吃饭
	public void eat() {
		synchronized (obj) {
			//当前哲学家的左右筷子都空闲  并且是饥饿状态  可以拿筷子
			if(!chopsticks[this.i]&&!chopsticks[(this.i+1)%5]&&
					!this.leftFlag&&!this.rightFlag&&this.hungry) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				chopsticks[(this.i+1)%5] = true; //筷子被拿起
				this.leftFlag=true;//左手有筷子
				System.out.println("哲学家"+this.i+"拿起了左边的筷子");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				chopsticks[this.i] = true; //筷子被拿起
				this.rightFlag=true;//右手有筷子
				System.out.println("哲学家"+this.i+"拿起了右边的筷子");
			}
		}
		if(this.leftFlag&&this.rightFlag&&this.hungry) {//满足条件  开始吃饭
			System.out.println("哲学家"+this.i+"开始吃饭");
			this.thinkFlag=false;//停止思考
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("哲学家"+this.i+"吃完饭了");
			this.hungry=false;//不饿
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("哲学家"+this.i+"洗净并放下了筷子");
			System.out.println("哲学家"+this.i+"开始思考");
			this.thinkFlag=true;//思考
			this.leftFlag=false;//左手放下筷子
			this.rightFlag=false;//右手放下筷子
			chopsticks[i] = false;
			chopsticks[(i+1)%5] = false;
		}
	}


	//思考
	public void think() {
		if(!this.leftFlag&&!this.rightFlag&&!this.thinkFlag) {
			thinkFlag = true;
			System.out.println("哲学家"+i+"开始思考");
		}
	}
	
	//线程方法
	@Override
	public void run() {
		while(true) {//循环判断每位哲学家的状态以及筷子的状态
			this.eat();
			this.think();
		}
	}
	
	//设置筷子状态
	public void setChopsticks(boolean[] chopsticks) {
		this.chopsticks = chopsticks;
	}
	
	//设置锁对象
	public void setObj(Object obj) {
		this.obj = obj;
	}
}

运行结果:
在这里插入图片描述在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云破丶日出

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值