多线程--哲学家就餐问题

这里写图片描述

1、当哲学家的左右筷子均是可用的时候才能就餐,否则等待,很容易理解,一次最多能有两个人同时就餐

public class PhilosopherEating 
{
    private static Thread[] threads = new Thread[5];
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
        for(int i = 0 ; i < 5; i ++){
            threads[i] = new Thread(new Philosopher(i));
            threads[i].start();
        }
        //当前线程组活动线程数
        while(Thread.activeCount()>1){
            Chopstick.monitor();
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ex){

            }
        }
    }
}
/*
*   哲学家进程
*/
class Philosopher implements Runnable
{
    //所有哲学家共用五支筷子
    private static Chopstick chopstick = new Chopstick();

    //哲学家编号
    private int id = 0;

    public Philosopher(int id){
        this.id = id;
    }

    public void run(){
        while(true){
            if(new Random().nextBoolean()){
                //取筷子
                chopstick.take(id);
                eat();
                //放筷子
                chopstick.down(id);

            }else{
                think();
            }
        }
    }
    //就餐
    private void eat(){
        int time = new Random().nextInt(10);
        try{
            System.out.println(id + "就餐"+time+"s");
            Thread.sleep(time*1000);
            System.out.println(id + "就餐完成!");
        }catch(InterruptedException ex){
            System.out.println("ex:eat");
        }
    }
    //思考
    private void think(){
        int time = new Random().nextInt(10);
        try{
            System.out.println(id + "思考"+time+"s");
            Thread.sleep(time*1000);
        }catch(InterruptedException ex){
            System.out.println("ex:think");
        }
    }

}
/*
*   筷子
*   作为资源
*/
class Chopstick
{
    private static Lock lock = new ReentrantLock();
    private static Condition chopstick = lock.newCondition();

    //五支筷子是否在使用
    private static boolean[] used = new boolean[5];

    //取筷子
    public void take(int id){
        //获取锁
        lock.lock();
        try{
            //左筷子,右筷子可以使用
            while(used[id] || used[(id+1)%5]){
                chopstick.await();
            }
            used[id] = true;
            used[(id+1)%5] = true;
        }catch(InterruptedException ex){

        }finally{
            //释放锁
            lock.unlock();
        }
    }
    //放筷子
    public void down(int id){
        lock.lock();
        used[id] = false;
        used[(id+1)%5] = false;
        chopstick.signalAll();
        lock.unlock();
    }
    //监控是否发生死锁,如果所有的筷子都是使用状态,则说明死锁
    public static boolean monitor(){
        boolean flag = true;
        for(int i = 0 ; i < 5 ; i ++ ){
            if(used[i] == false){
                flag = false;
                break;
            }
        }
        return flag;
    }
}

2、创建一个服务员,每次哲学家就餐都需要询问服务员

public class PhilosopherEating2 
{
    private static Thread[] threads = new Thread[5];
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
        for(int i = 0 ; i < 5; i ++){
            threads[i] = new Thread(new Philosopher(i));
            threads[i].start();
        }
        //当前线程组活动线程数
        while(Thread.activeCount()>1){
            if(Waiter.monitor()){
                System.out.println("死锁!!!!!!!!!!!!!!!!");
            }
            try{
                Thread.sleep(100);
            }catch(InterruptedException ex){

            }
        }
    }
}
/*
*   哲学家进程
*/
class Philosopher implements Runnable
{
    //服务员
    private static Waiter waiter = new Waiter();

    //哲学家编号
    private int id = 0;

    public Philosopher(int id){
        this.id = id;
    }

    public void run(){
        while(true){
            if(new Random().nextBoolean()){
                if(waiter.ask(id)){
                    eat();
                    waiter.put(id);
                }
            }else{
                think();
            }
        }
    }
    //就餐
    private void eat(){
        int time = new Random().nextInt(10);
        try{
            System.out.println(id + "就餐"+time+"s");
            Thread.sleep(time*100);
            System.out.println(id + "就餐完成!");
        }catch(InterruptedException ex){
            System.out.println("ex:eat");
        }
    }
    //思考
    private void think(){
        int time = new Random().nextInt(10);
        try{
            System.out.println(id + "思考"+time+"s");
            Thread.sleep(time*100);
        }catch(InterruptedException ex){
            System.out.println("ex:think");
        }
    }

}

/*
*   服务员
*/
class Waiter
{
    //五支筷子是否在使用
    private static boolean[] used = new boolean[5];

    //询问是否可以就餐
    public synchronized boolean ask(int id){
        if(used[id] || used[(id+1)%5]){
            return false;
        }
        used[id] = true;
        used[(id+1)%5] = true;
        return true;
    }
    //交筷子
    public synchronized void put(int id){

        used[id] = false;
        used[(id+1)%5] = false;

    }
    //监控是否发生死锁,如果所有的筷子都是使用状态,则说明死锁
    public static boolean monitor(){
        boolean flag = true;
        for(int i = 0 ; i < 5 ; i ++ ){
            if(used[i] == false){
                flag = false;
                break;
            }
        }
        return flag;
    }
}

3、使用信号量,每个哲学家只能先申请大号筷子,然后再申请小号筷子,即使是4号哲学家,也只能是先申请4号筷子,然后再申请0号筷子

public class PhilosopherEating3 
{
    private static Thread[] threads = new Thread[5];
    public static void main(String[] args) 
    {
        System.out.println("Hello World!");
        for(int i = 0 ; i < 5; i ++){
            threads[i] = new Thread(new Philosopher(i));
            threads[i].start();
        }
        //当前线程组活动线程数
        while(Thread.activeCount()>1){
            int count = 0;
            for(int i = 0 ; i < 5; i ++){
                if(threads[i].getState().equals(Thread.State.BLOCKED)){
                    count++;
                }
            }
            if(count == 5){
                System.out.println("死锁!!!!!!!!");
                for(int i = 0 ; i < 5; i ++ ){
                    System.out.println(threads[i].getState());
                }
            }
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ex){

            }
        }
    }
}
/*
*   哲学家进程
*/
class Philosopher implements Runnable
{
    //所有哲学家共用五支筷子
    private static Chopstick chopstick = new Chopstick();

    //哲学家编号
    private int id = 0;

    public Philosopher(int id){
        this.id = id;
    }

    public void run(){
        while(true){
            if(new Random().nextBoolean()){
                //取筷子
                chopstick.take(id);
                eat();
                //放筷子
                chopstick.down(id);

            }else{
                think();
            }
        }
    }
    //就餐
    private void eat(){
        int time = new Random().nextInt(10);
        try{
            System.out.println(id + "就餐"+time+"s");
            Thread.sleep(time*100);
            System.out.println(id + "就餐完成!");
        }catch(InterruptedException ex){
            System.out.println("ex:eat");
        }
    }
    //思考
    private void think(){
        int time = new Random().nextInt(10);
        try{
            System.out.println(id + "思考"+time+"s");
            Thread.sleep(time*100);
        }catch(InterruptedException ex){
            System.out.println("ex:think");
        }
    }

}
/*
*   筷子
*   作为资源
*/
class Chopstick
{

    //五支筷子资源
    private static Semaphore[] used = new Semaphore[5]; 

    public Chopstick(){
        for(int i = 0; i < 5; i ++){
            used[i] = new Semaphore(1);
        }
    }
    //取筷子
    public void take(int id){
        //获取锁
        try{
            if(id < 4){
                //先申请号大的筷子
                used[id+1].acquire();
                //申请号小的筷子
                used[id].acquire();
            }else{
                //id = 4时比较特殊
                //先申请号大的筷子
                used[id].acquire();
                //申请号小的筷子
                used[0].acquire();
            }
        }catch(InterruptedException ex){

        }finally{

        }
    }
    //放筷子
    public void down(int id){
        //先释放小号,再释放大号
        if(id < 4){
            used[id].release();
            used[id+1].release();
        }else{
            //id = 4时比较特殊
            used[0].release();
            used[id].release();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值