• 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个结果

      

           

  • 相关阅读:
    几个shell自动化脚本(定期清理、磁盘空间、搜寻关键字)
    linux系统垃圾清理
    mysql出现Got error 28 from storage engine错误
    WebBindingInitializer学习
    Java多线程异步调度程序分析(二)
    自己封装的C#操作redis公共类
    Java多线程编程的常见陷阱(转)
    Java分布式优秀资源集合
    JVM GC之对象生死
    Java内存模型
  • 原文地址:https://www.cnblogs.com/javabigdata/p/6837258.html
Copyright © 2020-2023  润新知