java中wait,notify,notifyAll,sleep方法的作用和区别

在进行多线程编程时,进程会遇到多线程之前的同步已经等待场景。
在java中,Object类提供了wait、nofity、notifyAll用来进行线程间的同步。一般如果我们调用wait、nofity、notifyAll都是结合synchronized同步关键字来使用:

 new Thread(()->{
            synchronized (monitor){

                try {
                    System.out.println("1. enter monitor ");
                    Thread.sleep(5000);
                    System.out.println("1. call wait ");
                    monitor.wait();
                    System.out.println("1. get monitor again ");
                    Thread.sleep(5000);
                    System.out.println("1. call notify ");
                    monitor.notify();
                    System.out.println("1. finished");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(()->{
            synchronized (monitor){
                try {
                    System.out.println("2. enter monitor ");
                    Thread.sleep(5000);
                    System.out.println("2. call notify ");
                    monitor.notify();
                    System.out.println("2. get monitor again ");
                    Thread.sleep(5000);
                    System.out.println("2. call monitor ");
                    monitor.wait();
                    System.out.println("2. finished ");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

打印:

1. enter monitor 
1. call wait 
2. enter monitor 
2. call notify 
2. get monitor again 
2. call monitor 
1. get monitor again 
1. call notify 
1. finished
2. finished 

在java中每个对象都有一个对象锁,里面会维护一个EntryList 中保存目前等待获取锁的线程,WaitSet 保存 wait 的线程。我们调用wait方法时,已经获得了对象锁的线程会让出锁进行阻塞等待,将当前线程放入到waitSet ,而调用notify之后,当前线程也会让出锁,然后从对象锁的waitSet中去一个线程进行唤醒。

这里有几个点需要注意,

  1. 调用wait方法的调用方必须是synchronized锁的持有者,如果是synchronized代码块,那么这个持有者就是同步的对象实例,如果是在类方法,那么就是这个类实例,如果在静态方法那么就是这个类本身
  2. 调用wait方法前,必须获取synchronized锁,也就是调用wait方法必须在synchronized的作用范围内,如果在其他地方调用,则会报如下错误:
Exception in thread "main" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at com.gridsum.ad.agg.query.platform.util.Utils.main(Utils.java:44)
  1. 调用wait方法后,线程进入阻塞等待,必须等待其他线程调用notify/notifyAll来进行唤醒

wait方法会释放当前已经获得的synchronized锁,直到其他线程调用notify/notifyAll唤醒重新竞争获取锁。

而Thread.sleep只是让线程进行休眠,不会释放任何锁资源。
而像Thread.sleep(0) 有点类似 Thread.yield(),表示出让当前CPU时间片,重新获取。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值