由多线程间通信引出的等待唤醒机制

案例: 
生产与消费分别开一个线程,生产一个产品消费一个产品,依次执行。 

public class ThreadDemo { 
  public static void main(String[] args) { 
    Resource r = new Resource(); 
    Producer producer = new Producer(r); 
    Consumer consumer = new Consumer(r); 
    Thread t1 = new Thread(producer); 
    Thread t2 = new Thread(consumer); 
    t1.start(); 
    t2.start(); 
  } 
} 
class Resource { 
  private String name; 
  private int count = 1; 
  private boolean flag = false; 
  public synchronized void set(String name) {//如果只有一个同步函数,可以使用同步函数,即在函数上加synchronzied。同步函数使用的锁是this。而当线程任务中需要多个同步时,必须用同步代码块,同步代码块使用的锁可以是任意对象。 
    if (flag) { 
      try { 
        this.wait(); 
      } catch (InterruptedException e) { 
        e.printStackTrace(); 
      } 
    } 
    this.name = name + count; 
    this.count++; 
    System.out.println(Thread.currentThread().getName() + " 生产者 " + this.name); 
    flag = true; 
    this.notify(); 
  } 
  public synchronized void out() { 
    if (!flag) { 
      try { 
        this.wait(); 
      } catch (InterruptedException e) { 
        e.printStackTrace(); 
      } 
    } 
    System.out.println(Thread.currentThread().getName() + " 消费者 " + this.name); 
    flag = false; 
    this.notify(); 
  } 
} 
class Producer implements Runnable { 
  private Resource r; 
  public Producer(Resource r) { 
    this.r = r; 
  } 
  public void run() { 
    while (true) { 
      r.set("面包"); 
    } 
  } 
} 
class Consumer implements Runnable { 
  private Resource r; 
  public Consumer(Resource r) { 
    super(); 
    this.r = r; 
  } 
  public void run() { 
    while (true) { 
      r.out(); 
    } 
  } 
} 

等待唤醒机制: 

wait(); 会让线程处于等待状态,其实就是将线程临时存储到了线程池中。(wait上面必须要有锁,即synchronized同步函数,线程池是靠锁划分的。) 
notify(); 会唤醒此线程池中任意一个等待的线程。 
notifyAll(); 会唤醒线程池中所有的等待线程。 
记住:上面的方法必须使用在同步中,因为必须要标识这些方法所属的锁。同一个锁上的notify只能唤醒该锁上的被wai的线程。 
为什么这些方法定义在Object类中呢? 
因为这些方法必须标识所属的锁,而锁可以是任意对象,任意对象可以调用的方法必然是Object类中的方法。

原文地址:https://www.cnblogs.com/yigechengxuyuan/p/8399667.html