java并发编程基础之等待通知机制wait/notify原理分析

          一个线程修改了一个对象的值,而另一个线程感知了变化,然后进行了相应的操作,整个过程开始于一个线程,结束于另一个线程。前者是生产者,后者是消费者,这种模式在功能层面上实现了解耦。

          有下面一段代码,大家可以根据执行的结果和注释很清晰的明确这个wait和notify的工作机制,wait等待释放锁。代码如下,不再做具体描述:

            

package juc.waitsleep;

/**
 * @Description   测试notify和wait机制
 * @Author DJZ-WWS
 * @Date 2019/5/15 11:44
 */
public class WaitNotify {
static  Object lock=new Object();
    static boolean flag=true;

    /**
     * 整个的一个执行流程wait线程先执行,执行到wait方法进行等待,进入等待队列,这时候释放锁,主线程休眠,
     * notify线程还没有开始进行工作,主线程休眠以后notify开始工作,由于wait已经将锁释放,所以notify会握住锁,
     * 执行了notify的业务以后将wait线程唤醒,这时候notify的业务还没有执行完,wait已经被唤醒,将进入阻塞队列,状态变为阻塞状态,
     * 后面notify进入二次加锁,等到这个里面的业务执行完以后,wait线程才能继续走后面的逻辑,从而将状态从阻塞变为运行
     *
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Thread waitThread = new Thread(new Wait(), "waitThread");
        waitThread.start();
        Thread.sleep(3000);
        Thread notifyThread = new Thread(new Notify(), "notifyThread");

        notifyThread.start();
    }

    static   class Wait implements   Runnable{
        @Override
        public void run() {
            //当条件不满足时继续wait,同时释放了lock锁
            synchronized (lock){
                  while (flag){
                  try {
                      System.out.println(Thread.currentThread().getName()+" falg is true"+" wait 线程进入等待状态");
                      lock.wait();//执行以后线程变为阻塞状态
                      System.out.println("wait 被唤醒"+"线程的状态为"+Thread.currentThread().getState());
                  }catch (Exception e){
                      e.printStackTrace();
                  }
                  }
                  //条件满足时完成工作
                System.out.println(Thread.currentThread().getName()+" flag is false ");
            }
        }
    }

    static   class  Notify implements   Runnable{
        @Override
        public void run() {
            synchronized (lock){
                //获取lock的锁,然后进行通知,通知不会释放lock的锁
                //直到当前线程释放了lock后,WaitThread才能从wait方法中返回
                System.out.println("notify 握住了锁");
            lock.notifyAll();;
            flag=false;
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //再次加锁
            synchronized (lock){
                //这个地方测试线程不会立马从wait返回,而是需要等待notify或者notifyall的线程释放锁之后,等待线程才有机会从wait返回
                System.out.println(Thread.currentThread().getName()+" 再次得到一个锁");
                try {
                    System.out.println(Thread.currentThread().getName()+"我将要睡3秒");
                    Thread.sleep(3000);
                    System.out.println(Thread.currentThread().getName()+"睡醒了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

输出的内容如下:

一些细节的总结

   1、wait()、notifyAll()时需要先对调用对象加锁

   2、调用wait方法之后线程状态由Running变为waiting,将当前线程放置到对象的等待队列。

   3 、notify或者notifyall方法调用后,等待线程不会从wait()方法返回,而是需要等到notify或者notifyall()的线程释放锁之后,等待线程才有机会从wait返回。

4、notify()方法将等待队列中的一个线程从等待队列移到同步队列,notifyall()方法将等待队列中的所有线程全部移到同步队列,被移动的线程状态由waiting变为blocking

5、从wait()返回的前提是获得了调用对象的锁。

工作原理如下图

wait线程首先获得了对象的锁,然后调用对象的wait方法,从而放弃了锁并进入了对象的等待队列WaitQueue,进入等待状态。由于wait线程释放了对象的锁,notify随后获取了对象的锁,并调用对象的notify方法,将等待线程移到SynchronizedQueue队列中,此时wait线程变为组神色状态。Notify释放了锁之后,wait线程再次获取到做并从wait()返回继续执行。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值