线程交互现象

线程交互现象

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

不好的解决方式

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

相关推荐
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
此时不提桶,更待何时2 天前
01-06-A-JVM排查实战详解
java·jvm