生产者与消费者案例

本文详细阐述了使用生产者与消费者模式实现的并发编程案例,通过创建生产者类与消费者类,以及线程操作Msg类来模拟同步与异步操作过程,确保数据的正确性和高效性。通过实例分析,解释了如何在多线程环境下实现资源的合理分配与利用,防止数据冲突和死锁情况的发生。

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

手头有两个人(也就是两个类),一个做存操作,一个做取操作,并且只有当存完或者取完方可进行令一个操作。以此达到循环输出的存取操作。

第一步:先写测试生产者类与消费者类  和 线程操作Msg类

//生产者
public class Product implements Runnable{
    private Msg msg = null; //线程操作对象
    public Product (Msg msg){
        super();
        this.msg = msg;
    }
    @override
    public void run(){
        for(int i=0;i<10;i++){
            if(i%2==0){
                   try{
                    this.msg.set("男","胡明明");
                }catch{
                    e.printStackTrace();
                }else{
                    this.msg.set("女","肖体秀");
                }
            }
        }
    
    }

}


//消费者
public class Consumer implements Runnable{
    private Msg msg = null;
     public Consumer (Msg msg){
        super();
        this.msg = msg;
    }
    
    @override
    public void run(){
        for(int i=0;i<10;i++){
            try{
                this.msg.get();
            }catch{
                e.printStackTrance();
            }
        }
    }

}

//线程操作Msg类
public class Msg{
    private String title;
    private String content;
    private boolearn flag = true;//true:生产者可以生产,不能取  false:消费者可以取,生产者不能生产
//多个线程访问统一资源。要考虑到数据是否同步的问题,当线程进入睡眠或者等待其它线程会趁虚而入,所以在方法加上一把锁

    public synchrnoized void set (String title,String content){
        if(this.flag == false){//存线程等待
        System.out.println(Thread.currentThread().getName()+ "进入等待")
        super.wait();
        }
        this.title = title;
        this.content = content;
        this.flag = false;//存完成,改变标识
        System.out.println(Thread.currentThread.getNmae() + "睡眠,并唤醒睡眠或者等待的线程")
        super.notify();//唤醒第一个等待的线程(取)
    }

    public synchrnoized void get(){
        if(this.flag == true){//取等待
            super.wait();
        }
        System.out.println(Thread.currentThread().getName() + this.title +"-----" +             this.content)
    this.flag = false;//存完成,改变标识
    super.notify();//唤醒第一个等待的线程(存)
    }

    public static void main(String[] args){
        Msg msg = new Msg();//实例化对象
        new Thread(msg,"存线程1")。start();
        new Thread(msg,"存线程2")。start();
        //new Thread(msg,"取线程")。start();
    }

}

/**
*实际上这个也很好理解,假设有两个线程,存线程和取线程(两个不同的操作类)被cpu调用,进入队列,假
*设存线程先被执行**那么,先走for循环第次存(同步,别的线程进不来)胡明明,当准备走第1次时,再次进
*行存的操作,发现存不了了,因为要存一次取一次,故将该线程进入睡眠状态,也就数阻塞。所以在外面伺机*已久的取线程进来了,进行取得操作,并唤醒其它睡眠或者等待的线程(期间存线程可能已经被唤醒了,进行*了存的操作)。当再次准备继续走循环时,同样跟存一样,也是必须一取一存才可以,由于标识符的改变,故*取线程进入睡眠。以此类推
*/

//当只有存取线程的时候确实是交易输出,但是我加了一个存线程,进入死锁。解析如下:

假设存1存2线程分别进入run方法,但是只能有一个人才能做存操作,假设有幸是存1,那么存1存完后,存方法被放开了,存1存2都有可能再次做存操作,但是,不管谁做存都做不了,要等到取做完才能做存,即会有两个存线程进入等待状态,随后只有当取线程唤醒其中一个线程后才能进行存的操作,那么它又将唤醒一个线程,那么到底是唤醒存1还是存2呢?先不管,假设唤醒了存1,那存1又该唤醒谁呢?如果唤醒的是存2呢?那么取线程也就只能睡着,即下一个存线程无法解放,两个存线程就只能一直等待着,三个进入死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值