线程间通信 | 等待唤醒机制

1.线程间通信

2.等待唤醒机制

3.等待唤醒案例

3.1简单生产者消费者案例

分析:

代码:

Object类中的方法
    void wait()   导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
    void notify() 唤醒正在等待对象监视器的单个线程。

package com.goldencis.thread;
/**
 * 等待唤醒案例 :线程之间的通信
 *     创建一个顾客进程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入waiting状态(无限等待)
 *     创建一个老板进程(生产者):花费5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子
 *
 * 注意:
 *    顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只有一个在执行
 *    同步使用的锁对象必须保证唯一
 *    只有锁对象才能调用wait和notify方法
 *
 * Object类中的方法
 *  void wait()   导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
 *  void notify() 唤醒正在等待对象监视器的单个线程。
 */
public class DemoWaitAndNotify {
    public static void main(String[] args) {
        //锁对象
        Object obj = new Object();
 
        //创建一个顾客进程(消费者)
        new Thread(){
            @Override
            public void run() {
               synchronized (obj){
                 while(true){
                     //告知老板要的包子的种类和数量
                     System.out.println("告知老板要的包子的种类和数量");
                     //调用wait方法,放弃cpu的执行,进入waiting状态(无限等待)
                     try {
                         obj.wait();
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     System.out.println("吃包子咯");
                 }
               }
            }
        }.start();
 
        //创建一个老板进程(生产者)
        new Thread(){
            //做好包子之后,调用notify方法,唤醒顾客吃包子
            @Override
            public void run() {
               while(true){
                   //花费5秒做包子,
                   try {
                       Thread.sleep(5000);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   synchronized (obj){
                       System.out.println("老板花费5秒做包子,唤醒顾客吃包子");
                       obj.notify();
                   }
               }
            }
        }.start();
    }
}

 进入计时等待有两种方式:
    sleep(long m)    在毫秒值结束之后,线程睡醒进入Runnable/Blocked状态

    wait(long m)      如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入Runnable/Blocked状态

唤醒方式:
    notify()               唤醒正在等待对象监视器的单个线程

    notifyAll()           唤醒正在等待对象监视器的所有线程

3.2 生产者与消费者案例

分析:

代码:

包子类Bun.java

package com.goldencis.thread.BunPAC;
 
/**
 * 包子类
 */
public class Bun {
    String pi;
    String xian;
    boolean flag;//包子资源是否存在
 
    public String getPi() {
        return pi;
    }
 
    public void setPi(String pi) {
        this.pi = pi;
    }
 
    public String getXian() {
        return xian;
    }
 
    public void setXian(String xian) {
        this.xian = xian;
    }
 
    public boolean isFlag() {
        return flag;
    }
 
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

生产者Producer.java

package com.goldencis.thread.BunPAC;
/**
 * 生产者
 */
public class Producer extends Thread{
    private Bun bun;//包子
    private Object obj;//锁对象
 
    public Producer(Bun bun, Object obj) {
        this.bun = bun;
        this.obj = obj;
    }
 
    @Override
    public void run() {
       while(true){
           synchronized (obj){
               //没有包子,生产包子
               if(bun.flag == false){
                   try {
                       Thread.sleep(2000);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println("包子铺生产了一个包子");
                   bun.flag = true;
                   obj.notify();//唤醒消费者
               // 有包子,等待
               }else{
                   try {
                       obj.wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    }
}

Consumer.java

package com.goldencis.thread.BunPAC;
/**
 * 消费者
 */
public class Consumer extends Thread{
    private Bun bun;//包子
    private Object obj;//锁对象
 
    public Consumer(Bun bun, Object obj) {
        this.bun = bun;
        this.obj = obj;
    }
 
    @Override
    public void run() {
       while (true){
           synchronized (obj){
               //有包子,吃包子
               if(bun.flag == true){
                   System.out.println("吃包子咯");
                   bun.flag = false;
                   obj.notify();//唤醒生产者
               //没有包子,等待
               }else{
                   try {
                       obj.wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    }
}

测试类Test.java

package com.goldencis.thread.BunPAC;
 
public class Test {
    public static void main(String[] args) {
        Bun bun =new Bun();
        bun.setFlag(false);
        Object obj = new Object();
        Producer p = new Producer(bun,obj);
        Consumer c = new Consumer(bun,obj);
        p.start();
        c.start();
    }
}

注:可以把包子(bun)作为锁对象,就不用创建Object对象了

原文地址:https://www.cnblogs.com/sx66/p/14308550.html