其他分享
首页 > 其他分享> > J-基础-线程-等待唤醒机制

J-基础-线程-等待唤醒机制

作者:互联网

线程状态:
1.新建(NEW):新建线程Thread,还未执行start()。
2.运行状态(Runnable):线程中的就绪(ready)和运行中(running)两种状态统称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3.阻塞(Blocked):表示线程阻塞于锁。
4.等待(Waiting):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5.超时等待(Timed Waiting):同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态 将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、 Object.wait。
6.终止(Teminated):因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
在这里插入图片描述
在这里插入图片描述
线程通信:
多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。
如生产者消费者问题,读者写者问题,处理同一数据,但是需要开启两个不同的线程任务。连个任务同时处理同一数据,两个线程存在线程通信问题。
等待唤醒机制:

  1. wait:线程不再活动,不再参与调度,进入 wait set 中,因此不会浪费 CPU 资源,也不会去竞争锁了,这时 的线程状态即是 WAITING。它还要等着别的线程执行一个特别的动作,也即是“通知(notify)”在这个对象 上等待的线程从wait set 中释放出来,重新进入到调度队列(ready queue)中
  2. notify:则选取所通知对象的 wait set 中的一个线程释放;例如,餐馆有空位置后,等候就餐最久的顾客最先 入座。
  3. notifyAll:则释放所通知对象的 wait set 上的全部线程。
    注:
    哪怕只通知了一个等待的线程,被通知线程也不能立即恢复执行,因为它当初中断的地方是在同步块内,而 此刻它已经不持有锁,所以她需要再次尝试去获取锁(很可能面临其它线程的竞争),成功后才能在当初调 用 wait 方法之后的地方恢复执行。
    调用wait和notify方法需要注意的细节:
  4. wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对 象调用的wait方法后的线程。
  5. wait方法与notify方法是属于Object类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继 承了Object类的。
  6. wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方 法。
    代码:
    包子铺线程生产包子,吃货线程消费包子。当包子没有时(包子状态为false),吃货线程等待,包子铺线程生产包子 (即包子状态为true),并通知吃货线程(解除吃货的等待状态),因为已经有包子了,那么包子铺线程进入等待状态。 接下来,吃货线程能否进一步执行则取决于锁的获取情况。如果吃货获取到锁,那么就执行吃包子动作,包子吃完(包 子状态为false),并通知包子铺线程(解除包子铺的等待状态),吃货线程进入等待。包子铺线程能否进一步执行则取 决于锁的获取情况。

代码:
main:

public class Main {

    private Boolean BaoziHave = false;

    public static void main(String[] args) {
        BaoZi baoZi = new BaoZi();

        Xiaofei xiaofei = new Xiaofei("消费者",baoZi);
        Shengchan shengchan = new Shengchan("生产者",baoZi);

        xiaofei.start();
        shengchan.start();
    }

}

BaoZi类:

public class BaoZi {
    String pier ;
    String xianer ;
    boolean flag = false ;//包子资源 是否存在 包子资源状态
}

Xioafei类

public class Xiaofei extends Thread {

    private BaoZi bz;
    public Xiaofei(String name,BaoZi bz){
        super(name); this.bz = bz;
    }

    @Override
    public void run() {
        while(true){
            synchronized (bz){
                if(bz.flag == false){//没包子
                     try {bz.wait();
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                }
                System.out.println("吃货正在吃"+bz.pier+bz.xianer+"包子");
                bz.flag = false;
                bz.notify();
            }
        }
    }
}

Shengchan类

public class Shengchan  extends Thread{
    private BaoZi bz;
    public Shengchan(String name,BaoZi bz){
        super(name); this.bz = bz;
    }

    @Override
    public void run() {
        int count = 0; //造包子
        while(true){ //同步
            synchronized (bz){
                if(bz.flag == true){//包子资源 存在
                    try {bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 没有包子 造包子
                System.out.println("包子铺开始做包子");
                if(count%2 == 0){ // 冰皮 五仁
                    bz.pier = "冰皮";
                    bz.xianer = "五仁";
                }else{// 薄皮 牛肉大葱
                    bz.pier = "薄皮";
                    bz.xianer = "牛肉大葱";
                }
                count++;
                bz.flag=true;
                System.out.println("包子造好了:"+bz.pier+bz.xianer);
                System.out.println("吃货来吃吧"); //唤醒等待线程 (吃货)
                 bz.notify();
            }
        }
    }
}

在这里插入图片描述

标签:等待,吃货,public,线程,唤醒,包子,bz,wait
来源: https://blog.csdn.net/qq_40811542/article/details/112989267