zoukankan      html  css  js  c++  java
  • java中wait和notify的关系

     java中,wait和notify这两个方法是一对,wait方法阻塞当前线程,而notify是唤醒被wait方法阻塞的线程。

        首先,需要说明的是,wait和notify方法都是Object的实例方法,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出IllegalMonitorStateException异常,所以这两个方法必须在同步块代码里面调用,经典的生产者和消费者模型就是使用这两个方法实现的。

        当前线程A获得对象obj的monitor,然后进入临界区(同步代码块),调用对象obj的wait方法,则线程A释放obj的monitor(执行了obj的wati方法之后,就会释放obj的monitor,不用等到执行完临界区,因为线程A会被阻塞在当前这个位置,同时cpu的相关寄存器会记住当前位置的堆栈信息),然后进入阻塞状态,同时线程A让出cpu,不再参与cpu的竞争,但是还会同时wait方法内部会不断地轮询线程A的InterruptStatus状态位(其实导致阻塞的方法一般都会做这个操作,就是不断地轮询中断状态位,以判断当前被阻塞的线程是否被提前取消了),以判断当前阻塞的状态是否会被中断(这里有点小矛盾,照理线程A不再参与cpu的竞争,又还不断轮询中断状态位,这个我还要研究下,有知道的可以留言评论指出,谢谢),等待其他线程调用A的notify(或notifyAll)来唤醒;然后线程B获取的obj的monitor之后,进去临界区,执行obj的notify方法,这时候,有点和wait方法不一样,就是调用了obj的notify之后,不会立刻释放obj的monitor同时唤醒线程A,而是要等到线程B执行完同步块代码,出了临界区,这时候才会释放obj的monitor,同时唤醒线程A,这时候线程A就会从新参与cpu的竞争,就有机会(因为可能其他线程也在竞争obj的monitor,如果之前有几个线程都在等待被obj的notify唤醒,则这时候就会有几个线程同时被唤醒,唤醒之后,因为obj的monitor同一时刻只允许一个线程拥有,所以被唤醒的几个线程究竟谁先获得obj的monitor继续往下面执行呢?这个就是根据操作系统的调度算法了。一个执行完同步块代码,释放obj的monitor之后,其他被唤醒的线程才会一个一个竞争获取obj的monitor,继续执行其wait方法后面的代码...)获取的obj的monitor,等到线程A重新获得obj的monitor之后,线程A会进入临界区,从wait方法后面继续执行(注意:这里进入临界区之后,不会从新从头执行临界区代码块,而会根据之前调用wait方法阻塞的时候,cpu记住的堆栈信息,会直接从wait方法后面的代码开始继续往下执行),直到出了临界区,释放obj的monitor。

        这里还有一个要注意的问题就是,wait和notify调用的顺序一定要注意先后,如果先调用了obj的notify,然后才调用obj的wait方法的话,则调用了wait方法被阻塞的线程则不会被唤醒,会一直处于阻塞状态。

        以下是我参考(https://www.cnblogs.com/ismallboy/p/6785312.html)代码做的实践:

        Service类

    /**
     * Created by mzy on 2019/1/23.
     */
    public class Service {
        public void testMethod(Object lock) {
            try {
                synchronized (lock) {
                    System.out.println("begin wait() ThreadName=" + Thread.currentThread().getName());
                    lock.wait();
                    if (Thread.currentThread().getName().equals("Thread-1")) {
                        Thread.sleep(50000);
                    }
                    System.out.println("end wait() ThreadName=" + Thread.currentThread().getName());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        public void synNotifyMethod(Object lock) {
            synchronized (lock) {
                System.out.println("begin notify() ThreadName=" + Thread.currentThread().getName());
                lock.notifyAll();
                System.out.println("end notify() ThreadName=" + Thread.currentThread().getName());
            }
        }
    }

        SynNotifyMethodThread类

    /**
     * Created by mzy on 2019/1/23.
     */
    public class SynNotifyMethodThread extends Thread {
        private Object lock;
        public SynNotifyMethodThread(Object lock) {
            super();
            this.lock = lock;
        }
        @Override
        public void run() {
            Service service = new Service();
            service.synNotifyMethod(lock);
        }
    }

        测试类

    /**
     * Created by mzy on 2019/1/20.
     */
    public class Test {
        public static void main(String[] args) {
            Object lock = new Object();
            ThreadA a = new ThreadA(lock);
            a.start();
            ThreadA b = new ThreadA(lock);
            b.start();
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SynNotifyMethodThread c = new SynNotifyMethodThread(lock);
            c.start();
        }
    }

        ThreadA类

    /**
     * Created by mzy on 2019/1/23.
     */
    public class ThreadA extends Thread{
        private Object lock;
        public ThreadA(Object lock) {
            super();
            this.lock = lock;
        }
        @Override
        public void run() {
            Service service = new Service();
            service.testMethod(lock);
        }
    }
  • 相关阅读:
    跨平台技术
    Unity和虚幻的比较
    商业模式(四):群硕软件,欧美客户为主的软件外包
    商业模式(四):群硕软件,欧美客户为主的软件外包
    Volley完全解析
    双十一京东图书购物清单,动动脑子节省300元
    双十一京东图书购物清单,动动脑子节省300元
    ListView异步加载图片,完美实现图文混排
    使用DrawerLayout实现QQ5.0侧拉菜单效果
    商业模式(三):P2P网贷平台,毛利润测算
  • 原文地址:https://www.cnblogs.com/tzeyeung/p/13531364.html
Copyright © 2011-2022 走看看