Java的线程中等待唤醒机制以消费者问题

文章详细解释了操作系统中的进程和线程概念,包括它们的内存空间、资源管理和状态转换。线程的等待唤醒机制在Java中通过wait(),notify(),notifyAll()方法实现,常用于线程间的协作,如生产者-消费者问题。文中通过一个包子铺和顾客的模拟示例展示了这一机制的工作原理。
摘要由CSDN通过智能技术生成

进程和线程都是操作系统中用于管理程序执行的概念。

进程是操作系统中的一个独立的执行单元,它包含了程序代码、数据、打开的文件、系统资源等信息。每个进程都有自己的内存空间和系统资源,不同的进程之间是相互独立的,它们不能直接访问彼此的内存空间和系统资源。进程的创建、销毁和切换都需要操作系统的支持,因此进程的开销比较大。

线程是进程中的一个执行单元,它是进程中的一个轻量级的执行流。每个线程都共享进程的内存空间和系统资源,不同的线程之间可以直接访问共享的内存空间和系统资源。线程的创建、销毁和切换比进程要快,因为它们不需要操作系统的支持,只需要使用线程库中的函数即可。

总之,进程和线程都是用于管理程序执行的概念,进程是操作系统中的一个独立的执行单元,线程是进程中的一个轻量级的执行流。进程和线程之间的区别在于内存空间和系统资源的共享方式,以及创建、销毁和切换的开销。
 

进程状态的转换

·就绪态→运行态:处于就绪态的进程被调度后,获得处理机资源(分派处理机时间片),于是进程由就绪态转换为运行态。
。运行态→就绪态:处于运行态的进程在时间片用完后,不得不让出处理机,从而进程由运行态转换为就绪态。此外,在可剥夺的操作系统中,当有更高优先级的进程就绪时,调度程序将正在执行的进程转换为就绪态,让更高优先级的进程执行。
·运行态一阻塞态:进程请求某一资源(如外设〉的使用和分配或等待某一事件的发生(如I/O操作的完成)时,它就从运行态转换为阻塞态。进程以系统调用的形式请求操作系统提供服务,这是一种特殊的、由运行用户态程序调用操作系统内核过程的形式。
阻塞态→就绪态:进程等待的事件到来时,如IO操作结束或中断结束时,中断处理程序必须把相应进程的状态由阻塞态转换为就绪态。
 

(1)线程中等待唤醒机制:

线程中等待唤醒机制是指线程在某些条件下被挂起,等待某些条件满足后被唤醒继续执行的机制。在Java中,线程的等待唤醒机制主要是通过wait()、notify()和notifyAll()方法来实现的。

当一个线程执行wait()方法时,它会释放持有的锁并进入等待状态,直到其他线程调用notify()或notifyAll()方法来唤醒它。notify()方法会随机唤醒一个正在等待的线程,而notifyAll()方法会唤醒所有正在等待的线程。被唤醒的线程会重新尝试获取锁并继续执行。

等待唤醒机制通常用于线程间的协作,例如生产者-消费者模型中,当队列为空时消费者线程会等待生产者线程生产数据并唤醒它,当队列满时生产者线程会等待消费者线程消费数据并唤醒它。通过等待唤醒机制,可以避免线程不必要的轮询和浪费CPU资源,提高程序的效率。

(2)经典的消费者问题:

顾客卖包子,店铺生产包子。

包子类(为简单演示,不再写入构造方法以及set和get方法)

public class Baozi {
    String pi;
    String xian;
    Boolean flag=false;
}

用包子店铺模拟线程一

//包子铺生产包子
public class BaoZiPu extends Thread {
    private Baozi baozi;

    public BaoZiPu(String name, Baozi baozi) {
        super(name);
        this.baozi = baozi;
    }
    int x=100;//假设包子铺一天生产100个包子
    @Override
    public void run() {
        int m=0;
        while (x>0) {
            synchronized (baozi) {
                if (baozi.flag==true){
                    try { baozi.wait(); }catch (InterruptedException e){e.printStackTrace();}
                }
                    System.out.println("包子铺生产包子");
                try {
                    Thread.sleep(180);//模拟做包子的过程耗费的时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (m%2==0){
                        baozi.pi="玉米面作皮";
                        baozi.xian="香菇肉丁做馅";
                    }else {
                        baozi.pi="白面作皮";
                        baozi.xian="雪菜做馅";
                    }
                    m++;x--;
                    System.out.println(baozi.pi+","+baozi.xian+"的包子一个"+",做的第"+(100-x)+"包子\n");
                    baozi.flag=true;
                    //唤醒
                    baozi.notify();

            }

        }
    }
}

用顾客来模拟线程二

public class Guke extends Thread {
    private Baozi baozi;

    public Guke(String name, Baozi baozi) {
        super(name);
        this.baozi = baozi;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (baozi) {
                if (baozi.flag == false) {
                    try {
                        baozi.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
                System.out.println("顾客吃包子。。。。");
                System.out.println("顾客吃" + baozi.pi + "," + baozi.xian + "的包子");
                try {
                    Thread.sleep(40);//模拟顾客吃包子的过程所耗费的时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("包子吃完了");
                baozi.flag = false;
                baozi.notify();
            }
        }
    }
}

定义测试类,来模拟该过程

public class Test {
    public static void main(String[] args) {
        Baozi baozi=new Baozi();//以包子作为共同的资源
        //线程一顾客
        Guke guke=new Guke("顾客",baozi);
        //线程二包子铺
        BaoZiPu baoZiPu=new BaoZiPu("包子铺",baozi);
        guke.start();
        baoZiPu.start();
    }
}

运行实例如下:(为方便演示,只显示前5个包子生产与消耗的模拟)

包子铺生产包子
玉米面作皮,香菇肉丁做馅的包子一个,做的第1包子
顾客吃包子。。。。
顾客吃玉米面作皮,香菇肉丁做馅的包子
包子吃完了
包子铺生产包子
白面作皮,雪菜做馅的包子一个,做的第2包子
顾客吃包子。。。。
顾客吃白面作皮,雪菜做馅的包子
包子吃完了
包子铺生产包子
玉米面作皮,香菇肉丁做馅的包子一个,做的第3包子
顾客吃包子。。。。
顾客吃玉米面作皮,香菇肉丁做馅的包子
包子吃完了
包子铺生产包子
白面作皮,雪菜做馅的包子一个,做的第4包子
顾客吃包子。。。。
顾客吃白面作皮,雪菜做馅的包子
包子吃完了
包子铺生产包子
玉米面作皮,香菇肉丁做馅的包子一个,做的第5包子
顾客吃包子。。。。
顾客吃玉米面作皮,香菇肉丁做馅的包子
包子吃完了

实机截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ヾ草木萤火(≧▽≦*)o

希望大家多多支持,我会继续分享

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值