当多线程并发的去执行任务,在进入临界区时为了使线程之间互不干扰,我们可以采用锁来避免同时使用资源产生冲突,例如synchronized修饰的代码块或函数,但是当一个任务与另一个任务的协作时,我们可以采用Object类提供的wait(),notify(),notfiyAll(),方法配合synchronized使用来完成任务与任务之间的握手。(Java SE5以后还提供了reetrantlock,condition..等用于同步和协作的类,在concurrent 包这里我们先不做介绍)这些方法必须在synchronized修饰的代码块或函数中使用,如果外层没有synchronized修饰,虽然能用过编译,但是在运行时会抛出IllegalMonitorStateException异常,即当前线程在没有获得锁的情况下非法的调用这些协作的方法。

wait():在获得锁的情况下,任务通常需要等待摸个条件发生,才能继续运行,调用wait()方法的线程会将自身挂起,释放锁。直到获取相同锁的别的线程,调用notify(),notifyAll(),该线程才有能被唤醒。

notify():在获取锁的情况下,当前线程调用notify()会随机唤醒一个在等待相同锁的线程,但是不能保证被唤醒的线程会有执行权限,被唤醒的线程还是需要和别的线程竞争资源在有可能获得锁。

notifyAll():在获取锁的情况下,当前线程调用会唤醒等待同一把锁而进入沉睡的所有线程。
下面将举一个生产者和消费者的例子来进一步阐述。
例子比较简单,有一家餐馆(Restaurant类),有一个消费者(Waiter类),有一个生产者(Producer类),还有一个订单类(Order),跑2个线程,一个用来跑waiter类,一个用来跑producer类,waiter的任务:获取当前对象的锁,如果订单对象为空,则进入等待,直到producer的任务在获取waiter对象锁的情况下调用了notifyAll()该任务,得以继续执行,获取producer对象的锁,将order变量置为null,完成消费,再唤醒producer对象。

package com.thread.study;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


enum Food{
    sandwich,hamburger,noodles,dumplings

}



public class Restaurant {
    Order order;
    Waiter waiter = new Waiter(this);
    Producer producer = new Producer(this);
    Thread threadone;
    Thread threadtwo;
    public Restaurant() {
        threadone = new Thread(waiter);
        threadtwo = new Thread(producer);
        threadone.start();
        threadtwo.start();
    }

    public Order randomGetFood(int orderNum){
        Random random = new Random();
        Food[] foods = Food.values();
        int len = foods.length;
        Food food = foods[random.nextInt(len)];
        return new Order(orderNum, food.name());
    }

    class Order{
        private int orderNumber;
        private String food;

        public Order(int orderNumber) {
            super();
            this.orderNumber = orderNumber;
        }

        public Order(int orderNumber, String food) {
            super();
            this.orderNumber = orderNumber;
            this.food = food;
        }

        @Override
        public String toString() {
            return "Order [orderNumber=" + orderNumber + ", food=" + food + "]";
        }


    }

    class Waiter implements Runnable{
        private Restaurant rt;

        public Waiter(Restaurant rt) {
            super();
            this.rt = rt;
        }


        @Override
        public void run() {

            while(!Thread.interrupted()){

                try {
                //获取当前对象的锁,如果订单对象为空,则进入等待
                    synchronized(this){
                        while(rt.order == null){
                            wait(); 
                        }
                    }
                    System.out.println("waiter get order " +rt.order);
                //获取producer对象。消费订单,重新唤醒producer任务。 
                    synchronized (rt.producer) {
                        rt.order =null;
                        rt.producer.notifyAll();                
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    System.out.println("waiter interrputed");
                }
            }

        }

    }

    class Producer implements Runnable{
        private Restaurant rt;
        private int count;
        public Producer(Restaurant rt) {
            super();
            this.rt = rt;
        }


        @Override
        public void run() {
            while(!Thread.interrupted()){
                try {
                //如果订单不为空,这进入等待
                    synchronized(this){
                        while(rt.order != null){
                            wait();
                        }
                    }
                    //当有20个订单时中断所有任务
                    if(++count == 20){
                        System.out.println(" end work");
                        rt.threadone.interrupt();
                        rt.threadtwo.interrupt();
                    }

                    System.out.println("complete producer");
                    //获取waiter对象锁,产生订单,唤醒water任务
                    synchronized(rt.waiter){
                        rt.order = randomGetFood(count);
                        rt.waiter.notifyAll();  
                    }

                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    System.out.println("producer interrupted");
                }

            }
            System.out.println("producer interrupted");

        }

    }

    public static void main(String[] args){  
        new Restaurant();
    }
}

java notify假唤醒 java notify notifyall_多线程