Java 多线程学习笔记 线程通讯 wait notify notifyAll的理解

来源:互联网 发布:原生js实现find方法 编辑:程序博客网 时间:2024/05/22 15:03


Java 多线程学习笔记 线程通讯 wait notify notifyAll的理解

wait()、 notify()、 notifyAll()是Object类的实例方法,是多线程之间通信的手段
2. wait():当某个条件无法满足,当前线程又没有能力解决时,等待直到条件满足
3. notify():当前线程认为其它线程所等待的条件已经满足时,通知
某个正在等待
的线程
4. notifyAll():当前线程认为其它线程所等待的条件已经满足时,通知
所有正在等
待的线程
5. 在使用这三个方法时,
必须先用synchronized获得对象的监视器

如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
    如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
    如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

看一个普通的等待方法: 消耗CPU,浪费资源


/** * 版权所有 (c) 2016,小明有限公司   */package ThreadTest;/** * 类说明: *  * <pre> * Modify Information: * Author        Date          Description * ============ =========== ============================ * wangxiaoming      2016-12-15    Create this file * </pre> *  */public class Waiter implements Runnable{    private boolean ready;    @Override    public void run() {        // TODO Auto-generated method stub        String name = Thread.currentThread().getName();        while(!ready){            System.out.println(name +" 焦急等待中。。。");        }        System.out.println(name + " 终于等到我了  !!!");    }            public static void main(String[] args) {        String name = Thread.currentThread().getName();        Waiter waiter = new Waiter();        //启动线程        new Thread(waiter).start();                try {            System.out.println(name+" 进程开始睡眠");            Thread.sleep(1);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        waiter.setReady(true);    }    /**     * @param ready the ready to set     */    public void setReady(boolean ready) {        this.ready = ready;    }}

代码的意思是 线程只有 主线程main 设置 ready = true的时候,线程才拿到资源进行


看一个生产者消费者模型:


生产者,是资源的提供者:

/** * 版权所有 (c) 2016,小明有限公司   */package ThreadTest;/** * 类说明: *  * <pre> * Modify Information: * Author        Date          Description * ============ =========== ============================ * wangxiaoming      2016-7-12    Create this file * </pre> *  */public class Producer {          public synchronized void createFood(){        //生产了一个food        //notifyAll();        notify();        System.out.println(Thread.currentThread().getName() + "  creat Food");    }    public static void main(String[] args) {                Producer producer = new Producer();        Consumer consumer1  = new Consumer(producer);//里面有构造函数,需要传递一个生产者        Consumer consumer2  = new Consumer(producer);                new Thread(consumer1).start();        new Thread(consumer2).start();                try {            Thread.sleep(1);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        producer.createFood();            }}

消费者:

若干个消费者竞争生产者资源:

生产者资源开始上锁, 只有notify 的时候,表示有可用的资源了

/** * 版权所有 (c) 2016,小明有限公司   */package ThreadTest;/** * 类说明: *  * <pre> * Modify Information: * Author        Date          Description * ============ =========== ============================ * wangxiaoming      2016-7-12    Create this file * </pre> *  */public  class Consumer implements Runnable {    private Producer producer;        public Consumer(Producer producer){        this.producer  = producer;    }    private void waitProducer(){        synchronized(producer){            try {                System.out.println(Thread.currentThread().getName() + " waiting producer food");                producer.wait();                System.out.println(Thread.currentThread().getName() + " get producer food");            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }  //等生产者,等待资源 表示等待producer                    }    }    @Override    public void run() {        // TODO Auto-generated method stub        waitProducer();    }        }

wait notify  notifyAll 都必须要配合synchronized 才可以使用

并且  wait() 到底是等待谁, 上面代码可以看到是等待资源的提供者 即生产者。

Thread-0 waiting producer foodThread-1 waiting producer foodmain  creat FoodThread-0 get producer food

1. 如果有多个线程在同时等待同一个资源时,notify()方法只能通知其中一个线程,具体是哪个线程是丌确定的,而其它没被唤醒的线程将被“饿死”2. 解决线程“饿死”,使用notifyAll(),线程将依次获得对象锁;或者设一个公共量,并且调用带时间参数的wait(long timeout)方法,当等待时间到之后,检查公共变量,如果丌满足条件,继续等待,否则结束等待3. wait()方法生效期间,对象锁是释放的,虽然它仍然在synchronized同步块中,这也是和sleep()的一大区别


生产者拥有生产者 这个对象的控制权 , 消费者需要 生产者的控制权, 生产者1 启动后跑到waitProducer 先获得生产者的控制权,打印出一句话,然后用wait 方法,释放生产者的控制权, 然后等着  进入阻塞状态, 生产者2 同理,  生产者createFood 就是告诉等待这个生产者资源的线程可以启动了


0 0