【Java学习】生产者消费者问题(23)

本文详细解析了操作系统课程中的经典问题——生产者消费者问题,通过PV操作实现互斥访问缓冲区,防止生产者和消费者同时操作导致的数据混乱。以包子生产和消费为例,介绍了如何使用Java的synchronized、wait和notify方法实现线程间的同步与唤醒。

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

生产者和消费者问题

在操作系统的课程中,生产者和消费者问题涉及PV操作(wait操作和signal操作),生产者消费者问题通俗的讲就是,当生产者生产的时候,消费者不能消费,消费者消费的时候,生产者不能生产,两者存在互斥访问缓冲区(放产品和取出产品的地方空间叫做缓冲区).

举例来说
现在有一个生产者在生产包子,一次生产一个,放入缓冲区,有一个消费者,一次买走一个包子,从缓冲区取走一个,现在缓冲区包子数量为0时,消费者就等待,生产者就生产包子,生产者生产了一个包子后,缓冲区包子数量就为1了,此时生产者阻塞,等待消费者消费.

代码演示:

Student的类(包子筐)

package com.westos.morning1;

class Student{
    public static String name;
    public static int age;
    public static boolean flag;//默认是false 代表没有资源,true 代表有资源
    
}

Set子线程(生产包子)

package com.westos.morning1;

public class SetThread extends Thread{
    Student student;
    public SetThread(Student student) {
        this.student=student;
    }

    @Override
    public void run() {
        int i=0;
        for (int j = 0; j < 100; j++) {
            synchronized (student){
                if(student.flag){
                    try {
                        student.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(i%2==0) {
                    student.name = "张三";
                    student.age = 33;
                }else {
                    student.name = "李四";
                    student.age = 44;
                }
                i++;
                student.flag=true;
                student.notify();//唤醒被阻塞的进程
           }
        }
    }
}


Get子线程(消费包子)

package com.westos.morning1;

public class GetThread extends Thread {
    Student student;

    public GetThread(Student student) {
        this.student = student;

    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (student) {
                if (student.flag) {
                    System.out.println(student.name + "===" + student.age);
                    student.flag = false;
                    student.notify();//唤醒被阻塞的
                }
                try {
                    student.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}


主线程

package com.westos.morning1;

public class Demo {
    public static void main(String[] args) {
        Student student = new Student();
        SetThread setThread = new SetThread(student);
        GetThread getThread = new GetThread(student);

        getThread.start();
        setThread.start();

    }
}


均匀运行,一个阻塞,一个被唤醒,一个被唤醒,另一个又阻塞,来回交替.
在这里插入图片描述


补充:
Object类中
wait()方法,使当前线程等待,一旦等待,就立马释放锁.下次被唤醒之后,从哪里等待的,就从哪里又开始执行
notify()方法,唤醒在此时监视器上等待的单个线程,被唤醒后,还得再次争抢时间片,不一定执行.

sleep()和wait()区别:
两个都能让线程处于阻塞状态.
sleep()必须传入时间量.
wait()可以传入时间量,也可以不传入.
sleep()线程休眠后,不释放锁.
wait()一旦等待,就立即释放锁.


谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值