哲学家进餐问题——分左右筷子法

博客介绍了使用Java实现多线程来模拟经典哲学家进餐问题的解决方案。通过创建ChopStick类表示筷子,Philosopher类表示哲学家,设置筷子的使用状态并实现同步操作。哲学家线程随机模拟思考和进食时间,完成取筷、用餐和放筷过程。在主类中初始化筷子和哲学家,并启动线程,展示了如何避免死锁并确保资源公平分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。

约束条件

(1)只有拿到两只筷子时,哲学家才能吃饭。

(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。

(3)任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子。

我的解决思路:

设计思路:使用三个类ChopStick,Philosopher,PhilosophersDinningProblem,分别在ChopStick中设置name,isused两个属性,第一个构造方法将属性赋初值,第二个方法pickup()进行取筷子操作,不可用的话该线程等待,可用的话将其赋为不可用false,第三个方法putdown()进行放筷子操作,将筷子状态赋为可用true,并使用notifyAll()唤醒所有等待线程。在类Philosopher中先实例化筷子的left和right对象,设置思考时间和进食时间thinking和eating,设置姓名name,第一个构造方法用于赋值,run()方法中先为每个线程设置一个随机思考时间thinking,思考后进行左筷子和右筷子的取筷子,若都取完的话,在设置一个随机进食时间eating,进食后放回两个筷子,在主类PhilosophersDinningProblem中先建立两个5大小的ChopStick和Philosopher数组,对一个字符串进行“哲学家i”初始化,筷子和哲学家数组进行赋值,最后将五个线程启动执行。

代码部分:

class ChopStick {
    String name;
    boolean isused;
    ChopStick(String name) {
        this.name = name;
        isused = true;
    }
    public synchronized void pickup() {
        try{
             while(!isused)
                 wait();
        }catch(InterruptedException e){}
        isused = false;
    }
    public synchronized void putdown() {
        isused = true;
        notifyAll();
    }
}
class Philosopher extends Thread{
    ChopStick left,right;
    int thinking;
    int eating;
    String name;
    Philosopher(String name,ChopStick c1,ChopStick c2){
        this.name=name;
        left=c1;
        right=c2;
    }
    public void run(){
        thinking = (int)(Math.random()*5000);
       try{
           sleep(thinking);
       }catch(InterruptedException e){}
       left.pickup();
       System.out.println(""+name+"拿起了左边的筷子"+left.name+"筷子");
       right.pickup();
        System.out.println(""+name+"拿起了右边的筷子"+right.name+"筷子");
        System.out.println(""+name+"开始吃饭");
        eating=(int)(Math.random()*5000);
        try {
            sleep(eating);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        left.putdown();
        System.out.println(""+name+"放下了左边的筷子"+left.name+"筷子");
        right.putdown();
        System.out.println(""+name+"放下了右边的筷子"+right.name+"筷子");
        System.out.println(""+name+"吃完了");
}}
public class PhilosophersDinningProblem {
    static ChopStick[] chopsticks=new ChopStick[5];
    static Philosopher[] philos=new Philosopher[5];
    public static void main(String args[]) {
           String[] phi =new String[5];
           for(int i=0;i<5;i++)
           {
               phi[i]="哲学家"+i;
           }
        for(int i=0;i<5;i++){
            chopsticks[i]=new ChopStick(String.valueOf(i));
        }
        for(int i=0;i<5;i++){
            philos[i]=new Philosopher(phi[i],chopsticks[i],chopsticks[(i+1)%5]);
        }
        for(int i=0;i<5;i++)
            philos[i].start();

    }
}

运行时截图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值