进程通讯-wait notify

2 篇文章 0 订阅
1 篇文章 0 订阅

进程通讯之wait/notify

wait():调用wait方法的线程释放当前的锁,并使当前线程处于等待状态。

notify():使用notify方法,使得用notify调用者对象作为Monitor的wait线程随机一个被唤醒。

notifyAll(): 使得用notifyAll()调用者对象作为Monitor的wait线程都被唤醒。

 

tip: 1. notifyAll()不是唤醒所有处于wait状态的线程,而是只唤醒使用当前调用notifyAll()对象作为Monitor的wait线程。

      2. wait和notify的锁对象及调用方法的对象必须是同一个,即当前线程的Monitor对象,否则发生IllegalMonitorStateException

 

/**
 * 进程通讯:wait notify
 */
public class WaitNotify {
    /**
     * 缓存WaitTarget任务的线程Monitor
     */
    public static ConcurrentHashMap<String,Object> waitPool = new ConcurrentHashMap<>();

    @Test
    public void test() throws InterruptedException {
        //创建等待任务
        WaitTarget waitTarget = new WaitTarget();
        //创建唤醒任务
        NotifyTarget notifyTarget = new NotifyTarget();
        //执行等待任务
        waitTarget.execWait();
        //执行唤醒任务
        notifyTarget.execNotify();

        try{
            //主线程休眠等待
            TimeUnit.DAYS.sleep(1);
        }catch (Exception e){

        }

    }

    /**
     * 等待任务
     */
    public class WaitTarget{
        public void execWait(){
            for (int i=0;i<10;i++){
                //创建10个线程,每个线程创建一个Monitor,然后调用Monitor的wait()方法,使得当前线程处于等待状态。
                new Thread(()->{
                    String key = UUID.randomUUID().toString();
                    Object monitor = new Object();
                    synchronized (monitor){
                        //将当前wait线程注册到等待池中,方便一会唤醒
                        WaitNotify.waitPool.put(key,monitor);
                        System.out.println(Thread.currentThread()+"正在等待,key="+key);
                        try {
                            monitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread()+"等待结束。。。。。。key="+key);
                    }
                }).start();
            }
        }
    }

    /**
     * 唤醒任务
     */
    public class NotifyTarget{
        public void execNotify() throws InterruptedException {
            //休眠2秒 让所有WaitTarget中的所有wait线程处于wait状态
            TimeUnit.SECONDS.sleep(2);
            System.out.println("开始notify");
//            WaitNotify.waitPool.forEach((k,v)->{
//                System.out.println("=========唤醒"+k);
//                synchronized (v){
//                    v.notify();
//                }
//            });
            String key = WaitNotify.waitPool.keys().nextElement();
            Object monitor = WaitNotify.waitPool.get(key);
            synchronized (monitor){
                System.out.println("key="+key+"被唤醒");
                monitor.notifyAll();
            }
        }
    }
}

执行结果如下:

可以看到,只有对应Monitor的wait线程被唤醒。即便是调用了notifyAll()方法,其他Monitor的wait线程同样还是处于wait状态。

如果线程在wait后没有释放锁,那么不可能进入notify代码段,因为使用的同一个Monitor对象作为锁,即同一把锁。

 

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。

  2. 关注公众号 『逆行的碎石机』,不定期分享原创知识。

  3. 同时可以期待后续文章ing🚀

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值