• 线程交互现象


    线程交互现象

    小明对自家的狗子有个规定,就是在狗狗还没吃完的时候,可以继续给他加饭

    不好的解决方式

    狗狗感觉一千年没吃饭了,狼吞虎咽起来,最后饭只剩下最后一点点,吃饭线程中使用while循环判断是否是1,如果是1那么就一直循环,知道加饭又重新回到了起点,这虽然是狗狗能够吃的更多,那么狗狗也会长得太胖了,太胖对狗狗健康有威胁,所以是一个不好的解决方式。

    package multiThread2;
    
    public class test {
        public static void main(String[] args) {
            Animal a = new Animal("大黄", 3, 10);
            Thread t1 = new Thread(){
                @Override
                public void run() {
                    while (true){
                        while (a.getFood()==1){
                            continue;
                        }
                        a.eatFood();
                        System.out.println(a.getName()+"吃饭,剩余"+a.getFood());
                        try {
                            Thread.sleep(1);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                }
            };
            t1.start();
            Thread t2 = new Thread(){
                @Override
                public void run() {
                    while (true){
                        a.addFood();
                        System.out.println(a.getName()+"加饭,剩余"+a.getFood());
                        try {
                            Thread.sleep(100);//这里注意,时间必须比上面多,不然无法看见饭剩下1
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                }
            };
            t2.start();
        }
    }
    
    package multiThread2;
    
    public class Animal{
        private String name;
        private int year;
        Animal(){}
        private int food;
        public Animal(String name,int year,int food){
            this.name = name;
            this.year = year;
            this.food = food;
        }
    
        @Override
        public String toString() {
            return "姓名:"+ name + ",年龄:" + year + ",来干饭了,还剩"+ food + "个食物";
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getYear() {
            return year;
        }
    
        public void setYear(int year) {
            this.year = year;
        }
    
        public int getFood() {
            return food;
        }
    
        public void setFood(int food) {
            this.food = food;
        }
        public synchronized void eatFood(){
            synchronized(this) {
                this.food--;
            }
        }
        public void addFood(){
            synchronized (this) {
                this.food++;
            }
        }
    }
    

    在这里插入图片描述

    使用wait和notify进行线程交互

    在Animal类中,eatfood方法,当food==1时,执行this.wait()
    this.wait()指的是暂停执行,释放占有
    进入eatfood方法,使用this.wait()可以让吃食物线程临时释放对this的占有,这样就有机会进入addfood方法了
    addfood:增加食物之后,执行this.notify
    this.notify表示通知等待this的线程,可以苏醒过来了。等待在this的线程,是吃饭过程。一旦addfood()结束,加食物线程释放了this,吃食物线程,重新占有this,执行后面的吃食物工作。

    package multiThread2;
    
    public class Animal{
       private String name;
       private int year;
       Animal(){}
       private int food;
       public Animal(String name,int year,int food){
           this.name = name;
           this.year = year;
           this.food = food;
       }
    
       @Override
       public String toString() {
           return "姓名:"+ name + ",年龄:" + year + ",来干饭了,还剩"+ food + "个食物";
       }
    
       public String getName() {
           return name;
       }
    
       public void setName(String name) {
           this.name = name;
       }
    
       public int getYear() {
           return year;
       }
    
       public void setYear(int year) {
           this.year = year;
       }
    
       public int getFood() {
           return food;
       }
    
       public void setFood(int food) {
           this.food = food;
       }
       public synchronized void eatFood(){
           if(food==1) {
               try{
                   this.wait();
               }catch (InterruptedException e){
                   e.printStackTrace();
               }
               this.food--;
           }
       }
       public synchronized void addFood(){
           this.food++;
           this.notify();
       }
    }
    
    package multiThread2;
    
    public class test {
       public static void main(String[] args) {
           Animal a = new Animal("大黄", 3, 10);
           Thread t1 = new Thread(){
               @Override
               public void run() {
                   while (true){
    //                    while (a.getFood()==1){
    //                        continue;
    //                    }
                       a.eatFood();
                       System.out.println(a.getName()+"吃饭,剩余"+a.getFood());
                       try {
                           Thread.sleep(1);
                       }catch (InterruptedException e){
                           e.printStackTrace();
                       }
                   }
               }
           };
           t1.start();
           Thread t2 = new Thread(){
               @Override
               public void run() {
                   while (true){
                       a.addFood();
                       System.out.println(a.getName()+"加饭,剩余"+a.getFood());
                       try {
                           Thread.sleep(100);
                       }catch (InterruptedException e){
                           e.printStackTrace();
                       }
                   }
               }
           };
           t2.start();
       }
    }
    

    在这里插入图片描述
    这里需要强调的是,wait方法和notify方法,并不是Thread线程上的方法,它们是Object上的方法。
    因为所有的Object都可以被用来作为同步对象,所以准确的讲,wait和notify是同步对象上的方法。
    wait()的意思是: 让占用了这个同步对象的线程,临时释放当前的占用,并且等待。 所以调用wait是有前提条件的,一定是在synchronized块里,否则就会出错。
    notify() 的意思是,通知一个等待在这个同步对象上的线程,你可以苏醒过来了,有机会重新占用当前对象了。
    notifyAll() 的意思是,通知所有的等待在这个同步对象上的线程,你们可以苏醒过来了,有机会重新占用当前对象了。

  • 相关阅读:
    【654. 最大二叉树】
    微信推送平台-测试号定制推送
    通过内网穿透实现文件共享,Python—行代码轻松实现公网访问
    设计模式(八)——装饰者模式
    Windows中的用户帐户与组账户
    再学责任链和代理模式
    EMS | 快递单号查询API
    Jetson Orin平台多路 FPDlink Ⅲ相机采集套装推荐
    k8s核心操作_使用k8s在一个pod中部署两个以上的容器_以及部署两个nginx尝试---分布式云原生部署架构搭建020
    Linux中断概述
  • 原文地址:https://blog.csdn.net/2301_79284357/article/details/140267599