Java语言实现操作系统经典同步问题之吸烟者问题

本文通过Java编程解决经典同步问题——吸烟者问题。描述了问题背景,即三个吸烟者分别拥有烟草、纸和火柴,由供应者随机提供资源。文中展示了桌子类、供应者类和吸烟者类的代码实现,并给出了运行结果。

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

百度全是伪代码,自己做的时候遇到了很多问题,倒腾了几个小时勉强实现了
贴一下代码吧,就是一个4线程并发的小程序

问题描述:
三个吸烟者在一个房间内,还有一个香烟供应者。为了制造并抽掉香烟,每个吸烟者需要三样东西:烟草、纸和火柴,供应 者有丰富货物提供。三个吸烟者中,第一个有自己的烟草,第二个有自己的纸,第三个有自己的火柴。供应者随机地将两样东西放在桌子上,允许一个吸烟者进行对健康不利的吸烟。当吸烟者完成吸烟后唤醒供应者,供应者再把两样东西放在桌子上,唤醒另一个吸烟者。
下面是代码:

桌子类(资源类):

public class Table {
    private  boolean end=true;//吸烟是否结束
    private  boolean offer1=false;//吸烟者1是否可以吸烟
    private  boolean offer2=false;//吸烟者2是否可以吸烟
    private  boolean offer3=false;//吸烟者3是否可以吸烟

    public boolean isEnd() {
        return end;
    }

    public void setEnd(boolean end) {
        this.end = end;
    }

    public boolean isOffer1() {
        return offer1;
    }

    public void setOffer1(boolean offer1) {
        this.offer1 = offer1;
    }

    public boolean isOffer2() {
        return offer2;
    }

    public void setOffer2(boolean offer2) {
        this.offer2 = offer2;
    }

    public boolean isOffer3() {
        return offer3;
    }

    public void setOffer3(boolean offer3) {
        this.offer3 = offer3;
    }


    public synchronized void provide(){
        int random= (int) (Math.random()*3);
        if(random==0){
            System.out.println("1是否可以开始吸烟:"+offer1);
            offer1=true;
            System.out.println("提供了烟草和纸");
        }else if(random==1){
            System.out.println("2是否可以开始吸烟:"+offer1);
            offer2=true;
            System.out.println("提供了纸和胶水");
        }else {
            System.out.println("3是否可以开始吸烟:"+offer1);
            offer3=true;
            System.out.println("提供了胶水和烟草");
        }
    }

    public synchronized void end(){
        if(offer1){
            offer1=false;//吸烟者不能连续多次吸烟
            System.out.println("吸烟者1吸烟结束");
            System.out.println("---------------------");
            setEnd(true);//吸烟结束 可以开始下一次随机分配资源
        }
        if(offer2){
            offer2=false;
            System.out.println("吸烟者2吸烟结束");
            System.out.println("---------------------");
            setEnd(true);
        }
        if(offer3){
            offer3=false;
            System.out.println("吸烟者3吸烟结束");
            System.out.println("---------------------");
            setEnd(true);
        }
    }

}

提供资源者类:

public class Provider extends Thread{
    private Table table;
    public Provider(Table table){
        this.table=table;
    }
    int count=0;
    @Override
    public void run() {
        while (true){
            while (table.isEnd()) {
                table.provide();
                table.setEnd(false);//提供资源后吸烟将开始,设为false
            }
        }
    }
}

吸烟者类,由于3个是一样的,这里只贴出一个:

public class SmokerOne extends Thread{
    private Table table;

    public SmokerOne(Table table){
        this.table=table;
    }

    @Override
    public void run() {
        while (true) {
            //System.out.println("吸烟者1请求资源");
            if (table.isOffer1()) {
                    smoke();//吸烟
                    table.end();//吸烟结束 end方法中设标志位true
            }
        }
    }

    private void smoke(){
        System.out.println("吸烟者1得到了烟草和纸,吸烟");
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        Table table=new Table();
        Provider provider=new Provider(table);
        SmokerOne s1=new SmokerOne(table);
        SmokerTwo s2=new SmokerTwo(table);
        SmokerThree s3=new SmokerThree(table);

        provider.start();
        s1.start();
        s2.start();
        s3.start();
    }
}

运行结果:

2是否可以开始吸烟:false
提供了纸和胶水
吸烟者2得到了纸和胶水,吸烟
吸烟者2吸烟结束
---------------------
2是否可以开始吸烟:false
提供了纸和胶水
吸烟者2得到了纸和胶水,吸烟
吸烟者2吸烟结束
---------------------
3是否可以开始吸烟:false
提供了胶水和烟草
吸烟者3得到了胶水和烟草,吸烟
吸烟者3吸烟结束
---------------------
1是否可以开始吸烟:false
提供了烟草和纸
吸烟者1得到了烟草和纸,吸烟
吸烟者1吸烟结束
---------------------
2是否可以开始吸烟:false
提供了纸和胶水
吸烟者2得到了纸和胶水,吸烟
吸烟者2吸烟结束
---------------------
1是否可以开始吸烟:false
提供了烟草和纸
吸烟者1得到了烟草和纸,吸烟
吸烟者1吸烟结束
---------------------
1是否可以开始吸烟:false
提供了烟草和纸
吸烟者1得到了烟草和纸,吸烟
吸烟者1吸烟结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值