线程交互现象

线程交互现象

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

不好的解决方式

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

相关推荐
caihuayuan514 分钟前
生产模式下react项目报错minified react error #130的问题
java·大数据·spring boot·后端·课程设计
一只码代码的章鱼19 分钟前
Spring Boot- 2 (数万字入门教程 ):数据交互篇
spring boot·后端·交互
编程、小哥哥20 分钟前
Java大厂面试:从Web框架到微服务技术的场景化提问与解析
java·spring boot·微服务·面试·技术栈·数据库设计·分布式系统
界面开发小八哥29 分钟前
「Java EE开发指南」如何使用MyEclipse的可视化JSF编辑器设计JSP?(二)
java·ide·人工智能·java-ee·myeclipse
韩仔搭建1 小时前
第二章:安卓端启动流程详解与疑难杂症调试手册
android·ui·娱乐
A-花开堪折1 小时前
Android7 Input(七)App与input系统服务建立连接
android
冰糖葫芦三剑客1 小时前
Android 自定义悬浮拖动吸附按钮
android
吃汉堡吃到饱1 小时前
【Android】从Choreographer到UI渲染(二)
android·ui
微信公众号:AI创造财富2 小时前
显示的图标跟UI界面对应不上。
android·ui
aningxiaoxixi2 小时前
安卓 Audio Stream 类型
android