zoukankan      html  css  js  c++  java
  • Java多线程系列4 线程交互(wait和notify方法)

    wait()/ notify()/ notifyAll()

    任何Object对象都可以作为这三个方法的主调,但是不推荐线程对象调用这些方法。

    1使用wait()、notify()和notifyAll()时需要首先对调用对象加锁【必须使用在同步代码块】
    2调用wait()方法后,线程状态会从RUNNING变为WAITING,并将当线程加入到lock对象的等待队列中【会释放锁】 ,后面的代码就不执行了 。当被唤醒并被执行时,是接着上次执行到的wait()方法代码后面继续往下执行的。
    3调用notify()或者notifyAll()方法后,等待在lock对象的等待队列的线程不会马上从wait()方法返回,必须要等到调用notify()或者notifyAll()方法的线程将lock锁释放,等待线程才有机会从等待队列返回。这里只是有机会,因为锁释放后,等待线程会出现竞争,只有竞争到该锁的线程才会从wait()方法返回,其他的线程只能继续等待

    下面代码演示 

    public class WaitNotifyThread {
        //条件是否满足的标志
        private static boolean flag = true;
        //对象的监视器锁
        private static Object lock = new Object();
    
        public static void main(String[] args){
            Thread waitThread = new Thread(new WaitThread(),"WaitThread");
            waitThread.start();
       
            Thread notifyThread = new Thread(new NotifyThread(),"NotifyThread");
            notifyThread.start();
        }
    
        /**
         * 等待线程
         */
        private static class WaitThread implements Runnable{
            public void run() {
                //加锁,持有对象的监视器锁
                synchronized (lock){
                    //只有成功获取对象的监视器才能进入这里
                    //当条件不满足的时候,继续wait,直到某个线程执行了通知
                    //并且释放了lock的监视器(简单来说就是锁)才能从wait
                    //方法返回
                    while (flag){
                        try {
                            System.out.println(Thread.currentThread().getName() + " flag is true"
                                   );
                            lock.wait(); //相当于睡眠 但是释放锁的
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //条件满足,继续工作
                    System.out.println(Thread.currentThread().getName() + " flag is false "
                           );
                }
            }
        }
    
        /**
         * 通知线程
         */
        private static class NotifyThread implements Runnable{
            public void run() {
                synchronized (lock){
                    //获取lock锁,然后执行通知,通知的时候不会释放lock锁
                    //只有当前线程退出了lock后,waitThread才有可能从wait返回
                    System.out.println(Thread.currentThread().getName() + " holds lock "
                           );
                    lock.notifyAll(); //唤醒wait 但是只有释放代码块以后  wait变成就绪  
                    flag = false;
                    try {
            			Thread.sleep(1000);
            		} catch (InterruptedException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		}
                }
                //再次加锁
                synchronized (lock){
                    System.out.println(Thread.currentThread().getName() + " holds lock again "
                           );
                    try {
            			Thread.sleep(1000);
            		} catch (InterruptedException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		}
                }
            }
        }
    }
    

      运行结果会有两种

      

      或者

      

     这个例子只是想说明 调用notify 或者notifyAll 并不会释放锁 要等到同步代码执行完成以后 才会释放  释放以后,两个线程的执行是不确定的 

     所以会有2个结果

      

           

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    关于模态/非模态对话框不响应菜单的UPDATE_COMMAND_UI消息(对对WM_INITMENUPOPUP消息的处理)
  • 原文地址:https://www.cnblogs.com/javabigdata/p/6837258.html
Copyright © 2011-2022 走看看