• notify和notifyAll的区别


    1、我们先验证下wait可以用notify和notifyAll来唤醒

    如下测试代码:

    public class WaitSleepDemo {
    
        public static void main(String[] args) {
            final  Object lock = new Object();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("thread A is waiting to get lock");
                    synchronized (lock){
    
                        try {
                            System.out.println("thread A get lock");
                            Thread.sleep(20);
                            System.out.println("thread A do wait method");
                            //无限期的等待
                            lock.wait();
                            //Thread.sleep(1000);
                            System.out.println("thread A is done");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
    
    
            //为了让Thread A 先于Thread B执行
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("thread B is waiting to get lock");
                    synchronized (lock){
                        try {
                            System.out.println("thread B get lock");
                            System.out.println("thread B is sleeping 10 ms");
                           Thread.sleep(10);
                           // lock.wait(10);
                            System.out.println("thread B is done");
                            //这句注释掉,thread A is done就不会被打印
                            lock.notify(); // lock.notifyAll();
                           
    
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    
                    }
                }
            }).start();
        }
    }
    

      

      执行结果:

    thread A is waiting to get lock
    thread A get lock
    thread B is waiting to get lock
    thread A do wait method
    thread B get lock
    thread B is sleeping 10 ms
    thread B is done
    thread A is done
    

      

    2、notify和notifAll的区别

    两个概念

    锁池EntryList

    等待池 WaitSet

    锁池:

    假设线程A已经拥有了某个对象(不是类)的锁,而其它线程B,C想要调用这个对象的某个某个synchronized方法(或者块)之前必须获得该对象锁的拥有权,而恰巧该对象的锁目前正被A所占有,此时B, C线程就会被阻塞,进入一个地方去等待锁的释放,这个地方便是该对象的锁池。

    等待池

       假设线程A调用了某个对象的wait方法,线程A就会释放该对象的锁,同时线程A就进入到了该对象的等待池中,进入等待池中的线程不会去竞争该对象的锁。

     notify和notifAll的区别

    notifyAll: 会让所有处于等待池的线程全部进入锁池去竞争获取锁的机会

    notify: 只会随机选取一个处于等待池中的线程进入锁池去竞争获取锁的机会。

    如下的测试代码

    public class NotificationDemo {
        private volatile boolean go = false;
    
    
        private synchronized  void shouldGo() throws InterruptedException {
    
            while (go != true){
                System.out.println(Thread.currentThread() + " is going to wait on this object");
                wait();
                System.out.println(Thread.currentThread() + " is woken up");
    
            }
            go = false; //reseting condition
        }
    
    
        private synchronized  void go() throws InterruptedException {
    
            while (go == false){
                System.out.println(Thread.currentThread() + " is going to notify all or one ");
                go = true;
    
                notify();
            }
    
        }
    
    
    
        public static void main(String[] args) throws InterruptedException {
    
            NotificationDemo test = new NotificationDemo();
    
              Runnable waitTak = new Runnable() {
                @Override
                public void run() {
                    try {
                        test.shouldGo();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " finish execution");
                }
            };
    
             Runnable notifyTask = new Runnable() {
                @Override
                public void run() {
                    try {
                        test.go();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " finish execution");
                }
            };
    
            Thread t1 = new Thread(waitTak, "WT1");
            Thread t2 = new Thread(waitTak, "WT2");
            Thread t3 = new Thread(waitTak, "WT3");
            t1.start();
            t2.start();
            t3.start();
    
            Thread t4 = new Thread(notifyTask, "NT1");
            Thread.sleep(200);
            t4.start();
    
    
        }
    }
    

      打印结果:

    Thread[WT1,5,main] is going to wait on this object
    Thread[WT2,5,main] is going to wait on this object
    Thread[WT3,5,main] is going to wait on this object
    Thread[NT1,5,main] is going to notify all or one 
    Thread[WT1,5,main] is woken up
    NT1 finish execution
    WT1 finish execution
    

      多执行几次,可以发现notify调用后,被唤醒的线程是随机的。

    将notify改成notifyAll

     打印结果如下:

    Thread[WT1,5,main] is going to wait on this object
    Thread[WT3,5,main] is going to wait on this object
    Thread[WT2,5,main] is going to wait on this object
    Thread[NT1,5,main] is going to notify all or one 
    Thread[WT2,5,main] is woken up
    Thread[WT3,5,main] is woken up
    Thread[WT3,5,main] is going to wait on this object
    NT1 finish execution
    Thread[WT1,5,main] is woken up
    Thread[WT1,5,main] is going to wait on this object
    WT2 finish execution
    

      说明三个线程都被唤醒了

  • 相关阅读:
    Json处理函数json_encode json_decode
    会员注册审核状态更新计算
    $_GLOBALS超全局数组和global定义的全局变量区别?
    $_CFG = load_config(); /* 载入系统参数 */
    window.clearInterval与window.setInterval的用法 定时器的设置
    php中文件引入require
    修改本地数据库root权限密码
    JQuery执行函数与window.onload函数
    Android 启动白屏或者黑屏闪现解决
    Android状态栏微技巧,带你真正意义上的沉浸式
  • 原文地址:https://www.cnblogs.com/linlf03/p/12113185.html
Copyright © 2020-2023  润新知