哲学家就餐问题(java实现)

1 问题概述
哲学家就餐问题,是并行程序中的一个经典问题,其描述如下。
1. 圆桌上有五位哲学家,每两人中间有一个筷子。
2. 每个哲学家有两件事情要做:
    (1) 思考;
    (2) 吃饭。哲学家必须同时拿到两只筷子,才能吃饭。
3. 哲学家之间并不知道对方何时要吃饭,何时要思考,不能协商制定分时策略。
4. 设计一个拿筷子的策略,使得哲学家之间不会因为拿筷子而出现死锁或者活锁。

2代码实现

  • 版本一(没有很好的解决死锁问题)

       当五个哲学家同时拿起左筷子,进入死锁状态

package com.cch;

public class Philosopher extends Thread{
	private static int[] chopsticks = {1,1,1,1,1};
	private int id;
	
	public Philosopher(int id){
		this.id = id;
	}
	
	@Override
	public synchronized void run() {
		this.eat();
		this.think();
	}
	
	public void think(){
		//左筷子放下
		this.chopsticks[this.id] = 1;
		//右筷子放下
		this.chopsticks[(this.id+1)%this.chopsticks.length] = 1;
		System.out.println("哲学家_" + this.id + "正在思考");
		
		//思考一秒时间
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void eat(){
		//拿起左筷子
		while(true){
			if(this.chopsticks[this.id] != 0){
				chopsticks[this.id] = 0;
				System.out.println("哲学家_" + this.id + "拿起了左筷子");
				break;
			}else{
				try {
					this.wait(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					System.out.println("哲学家_" + this.id + "的左筷子正在被哲学家_"+((this.id-1+this.chopsticks.length)%this.chopsticks.length)+"使用,等待1000ms");
				}
			}
		}
		
		
		//拿起右筷子
		while(true){
			if(this.chopsticks[(this.id+1)%this.chopsticks.length] != 0){
				chopsticks[(this.id+1)%this.chopsticks.length] = 0;
				System.out.println("哲学家_" + this.id + "拿起了右筷子");
				break;
			}else{
				try {
					this.wait(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					System.out.println("哲学家_" + this.id + "的右筷子正在被哲学家_"+((this.id+1)%this.chopsticks.length)+"使用,等待1000ms");
				}
			}
		}
		System.out.println("哲学家_" + this.id + "正在吃饭");
		
		//吃饭花一秒时间
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.notify();
	}
	
	public static void main(String[] args) {
		new Philosopher(0).start();
		new Philosopher(1).start();
		new Philosopher(2).start();
		new Philosopher(3).start();
		new Philosopher(4).start();
	}
}

  • 版本二(超时释放法)

    当五个哲学家同时拿起左筷子时,线程进入死锁,等待2s后,就会有哲学家会放下右筷子,死锁解除

package com;

public class Philosopher extends Thread{
	private static int[] chopsticks = {1,1,1,1,1};
	private int id;
	
	public Philosopher(int id){
		this.id = id;
	}
	
	@Override
	public synchronized void run() {
		this.eat();
		this.think();
	}
	
	public void think(){
		//左筷子放下
		this.chopsticks[this.id] = 1;
		//右筷子放下
		this.chopsticks[(this.id+1)%this.chopsticks.length] = 1;
		System.out.println("哲学家_" + this.id + "正在思考");
		
		//思考一秒时间
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void eat(){
		//拿起左筷子
		while(true){
			if(this.chopsticks[this.id] != 0){
				chopsticks[this.id] = 0;
				System.out.println("哲学家_" + this.id + "拿起了左筷子");
				break;
			}else{
				try {
					this.wait(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					System.out.println("哲学家_" + this.id + "的左筷子正在被哲学家_"+((this.id-1+this.chopsticks.length)%this.chopsticks.length)+"使用,等待1000ms");
				}
			}
		}
		
		
		//拿起右筷子
		while(true){
			if(this.chopsticks[(this.id+1)%this.chopsticks.length] != 0){
				chopsticks[(this.id+1)%this.chopsticks.length] = 0;
				System.out.println("哲学家_" + this.id + "拿起了右筷子");
				break;
			}else{
				try {
					this.wait(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					System.out.println("哲学家_" + this.id + "的右筷子正在被哲学家_"+((this.id+1)%this.chopsticks.length)+"使用,等待1000ms");
				}
			}
		}
		System.out.println("哲学家_" + this.id + "正在吃饭");
		
		//吃饭花一秒时间
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.notify();
	}
	
	public static void main(String[] args) {
		new Philosopher(0).start();
		new Philosopher(1).start();
		new Philosopher(2).start();
		new Philosopher(3).start();
		new Philosopher(4).start();
	}
}

  • 版本三(服务生解法)

    添加一个服务生,只有当经过服务生同意之后才能拿筷子,服务生负责避免死锁发生。

package com.cch.Philosopher;

class Philosopher extends Thread{
    private String name;
    private Fork fork;
    public Philosopher(String name,Fork fork){
        super(name);
        this.name=name;
        this.fork=fork;
    }
    
    public void run(){
        while(true){
            thinking();
            fork.takeFork();
            eating();
            fork.putFork();
        }
        
    }
    
    
    public void eating(){
        System.out.println("I am Eating:"+name);
        try {
            sleep(1000);//吃饭花一秒
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    
    public void thinking(){
        System.out.println("I am Thinking:"+name);
        try {
            sleep(1000);//思考花一秒
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

class Fork{
    private boolean[] used={false,false,false,false,false,false};
    
    /*只有当左右手的筷子都未被使用时,才允许获取筷子,且必须同时获取左右手筷子*/
    public synchronized void takeFork(){
        String name = Thread.currentThread().getName();
        int i = Integer.parseInt(name);
        while(used[i]||used[(i+1)%5]){
            try {
                wait();//如果左右手有一只正被使用,等待
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        used[i ]= true;
        used[(i+1)%5]=true;
    }
    
    /*必须同时释放左右手的筷子*/
    public synchronized void putFork(){
        String name = Thread.currentThread().getName();
        int i = Integer.parseInt(name);
        
        used[i ]= false;
        used[(i+1)%5]=false;
        notifyAll();//唤醒其他线程
    }
}

public class ThreadTest {

    public static void main(String []args){
        Fork fork = new Fork();
        new Philosopher("0",fork).start();
        new Philosopher("1",fork).start();
        new Philosopher("2",fork).start();
        new Philosopher("3",fork).start();
        new Philosopher("4",fork).start();
    }
}
  • 版本四(资源分级法)

    请自行百度

  • 版本五(Chandy/Misra解法)

    请自行百度



  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cchoop

有用的话请杯肥宅水

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

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

打赏作者

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

抵扣说明:

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

余额充值