zoukankan      html  css  js  c++  java
  • Java Object对象中的wait,notify,notifyAll的理解

    wait,notify,notifyAll 是定义在Object类的实例方法,用于控制线程状态,在线程协作时,大家都会用到notify()或者notifyAll()方法,其中wait与notify是java同步机制中重要的组成部分,需要结合与synchronized关键字才能使用,在调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(object){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:java.lang.IllegalMonitorStateException:current thread not owner(意思是因为没有同步,所以线程对对象锁的状态是不确定的,不能调用这些方法)。

    wait的目的就在于暴露出对象锁,所以需要保证在lock的同步代码中调用lock.wait()方法,让其他线程可以通过对象的notify叫醒等待在该对象的等该池里的线程。同样notify也会释放对象锁,在调用之前必须获得对象的锁,不然也会报异常。所以,在线程自动释放其占有的对象锁后,不会去申请对象锁,只有当线程被唤醒的时候或者达到最大的睡眠时间,它才再次争取对象锁的权利

    主要方法:

    (1).wait()
    等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

    (2).notify()
    唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

    (3).notifyAll()
    唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

    通过一个实例来看一下实际的效果,开启两个线和,一个线程 打印1到52的数字,一个打印A到Z的字母,要求,打印两个数,打印一个字母,这样交替顺序打印,代码如下:

    /**
     * create by spy on 2018/6/4
     */
    public class ShuZiZiMuThread {
    
        public static void main(String[] args) {
            Object object = new Object();
            shuzi shuzi = new shuzi(object);
            zimu zimu = new zimu(object);
            Thread t = new Thread(shuzi);
            t.setName("shuzi");
            Thread t1 = new Thread(zimu);
            t1.setName("zimu");
            t.start();//数字线程先运行
            t1.start();
        }
    }
    
    
    class shuzi implements Runnable{
        private Object object;
        //声明类的引用
        public shuzi(Object object) {
            this.object = object;
        }
    
        public void run() {
            synchronized (object) {//上锁
    
                for(int i=1;i<53;i++){
                    System.out.print(i+",");
                    if(i%2==0){
                        object.notifyAll();//唤醒其它争夺权限的线程
                        try {
                            object.wait();//释放锁,进入等待
                            System.out.println("数字打印类打全打印当前对象拥有对象锁的线程"+Thread.currentThread().getName());//输出当前拥有锁的线程名称
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    
    }
    
    class zimu implements Runnable{
        private Object object;
        public zimu(Object object) {
    
            this.object = object;
        }
        public void run() {
            synchronized (object) {
                for(int j=65;j<91;j++){
                    char c = (char)j;
                    System.out.print(c);
                    object.notifyAll();//唤醒其它争夺权限的线程
                    try {
                        object.wait();//释放锁,进入等待
                        System.out.println("字母打印类打全打印当前对象拥有对象锁的线程"+Thread.currentThread().getName());//输出当前拥有锁的线程名称
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }

    实际运行的结果 :

    1,2,A数字打印类打印当前对象拥有对象锁的线程shuzi
    3,4,字母打印类打印当前对象拥有对象锁的线程zimu
    B数字打印类打印当前对象拥有对象锁的线程shuzi
    5,6,字母打印类打印当前对象拥有对象锁的线程zimu
    C数字打印类打印当前对象拥有对象锁的线程shuzi
    7,8,字母打印类打印当前对象拥有对象锁的线程zimu
    D数字打印类打印当前对象拥有对象锁的线程shuzi
    9,10,字母打印类打印当前对象拥有对象锁的线程zimu
    E数字打印类打印当前对象拥有对象锁的线程shuzi
    11,12,字母打印类打印当前对象拥有对象锁的线程zimu
    F数字打印类打印当前对象拥有对象锁的线程shuzi
    13,14,字母打印类打印当前对象拥有对象锁的线程zimu
    G数字打印类打印当前对象拥有对象锁的线程shuzi
    15,16,字母打印类打印当前对象拥有对象锁的线程zimu
    H数字打印类打印当前对象拥有对象锁的线程shuzi
    17,18,字母打印类打印当前对象拥有对象锁的线程zimu
    I数字打印类打印当前对象拥有对象锁的线程shuzi
    19,20,字母打印类打印当前对象拥有对象锁的线程zimu
    J数字打印类打印当前对象拥有对象锁的线程shuzi
    21,22,字母打印类打印当前对象拥有对象锁的线程zimu
    K数字打印类打印当前对象拥有对象锁的线程shuzi
    23,24,字母打印类打印当前对象拥有对象锁的线程zimu
    L数字打印类打印当前对象拥有对象锁的线程shuzi
    25,26,字母打印类打印当前对象拥有对象锁的线程zimu
    M数字打印类打印当前对象拥有对象锁的线程shuzi
    27,28,字母打印类打印当前对象拥有对象锁的线程zimu
    N数字打印类打印当前对象拥有对象锁的线程shuzi
    29,30,字母打印类打印当前对象拥有对象锁的线程zimu
    O数字打印类打印当前对象拥有对象锁的线程shuzi
    31,32,字母打印类打印当前对象拥有对象锁的线程zimu
    P数字打印类打印当前对象拥有对象锁的线程shuzi
    33,34,字母打印类打印当前对象拥有对象锁的线程zimu
    Q数字打印类打印当前对象拥有对象锁的线程shuzi
    35,36,字母打印类打印当前对象拥有对象锁的线程zimu
    R数字打印类打印当前对象拥有对象锁的线程shuzi
    37,38,字母打印类打印当前对象拥有对象锁的线程zimu
    S数字打印类打印当前对象拥有对象锁的线程shuzi
    39,40,字母打印类打印当前对象拥有对象锁的线程zimu
    T数字打印类打印当前对象拥有对象锁的线程shuzi
    41,42,字母打印类打印当前对象拥有对象锁的线程zimu
    U数字打印类打印当前对象拥有对象锁的线程shuzi
    43,44,字母打印类打印当前对象拥有对象锁的线程zimu
    V数字打印类打印当前对象拥有对象锁的线程shuzi
    45,46,字母打印类打印当前对象拥有对象锁的线程zimu
    W数字打印类打印当前对象拥有对象锁的线程shuzi
    47,48,字母打印类打印当前对象拥有对象锁的线程zimu
    X数字打印类打印当前对象拥有对象锁的线程shuzi
    49,50,字母打印类打印当前对象拥有对象锁的线程zimu
    Y数字打印类打印当前对象拥有对象锁的线程shuzi
    51,52,字母打印类打印当前对象拥有对象锁的线程zimu
    Z数字打印类打印当前对象拥有对象锁的线程shuzi

    结果分析:

    通过结果可以看出:

    在字母打一打印类里 调用完

    object.notifyAll();//唤醒其它争夺权限的线程
    object.wait();//释放锁,进入等待
    后,拥有对象锁的线程是shuzi

    在数字打印类里 调用完

    object.notifyAll();//唤醒其它争夺权限的线程
    object.wait();//释放锁,进入等待
    后,拥有对象锁的线程是zimu
  • 相关阅读:
    将.net core api 部署成windows服务
    根据2个经纬度点,计算这2个经纬度点之间的距离(通过经度纬度得到距离)
    .NET 基础知识 单文件部署和可执行文件 剪裁独立部署和可执行文件
    通过 InnoSetup 美化安装界面
    拼凑一个ABP VNext管理后台拼凑一个ABP VNext管理后台
    互联网软件的安装包界面设计Inno setup
    weinre  远程实时调试手机上的Web页面 JAVASCRIPT远程调试
    asp.net core web应用以服务的方式安装运行
    用 vue2 和 webpack 快速建构 NW.js 项目
    谷歌插件抓包 similarweb抓包
  • 原文地址:https://www.cnblogs.com/songpingyi/p/9134805.html
Copyright © 2011-2022 走看看