线程交互现象

线程交互现象

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

不好的解决方式

狗狗感觉一千年没吃饭了,狼吞虎咽起来,最后饭只剩下最后一点点,吃饭线程中使用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() 的意思是,通知所有的等待在这个同步对象上的线程,你们可以苏醒过来了,有机会重新占用当前对象了。

相关推荐
百锦再5 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
JH30735 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
2501_916008896 小时前
全面介绍Fiddler、Wireshark、HttpWatch、SmartSniff和firebug抓包工具功能与使用
android·ios·小程序·https·uni-app·iphone·webview
Coder_Boy_6 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
玉梅小洋7 小时前
Windows 10 Android 构建配置指南
android·windows
invicinble7 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟7 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖7 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
Libraeking8 小时前
视觉篇:Canvas 自定义绘图与高级动画的华丽圆舞曲
android·经验分享·android jetpack
qq_12498707538 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计