为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object类里

关于wait()、notify()的使用
public class WaitDemo {
    public static Object object = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
 
    static class Thread1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("线程" + Thread.currentThread().getName() + "开始执行!");
                try {
//                    System.out.println("线程" + Thread.currentThread().getName() + "调用了wait()");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁!");
            }
        }
    }
 
    static class Thread2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("线程" + Thread.currentThread().getName() + "调用了notify()");
            }
        }
    }
}

从代码中还可以看出这样的一个问题,就是我们在两个线程中所用的是一个对象,在Thread1中我们使用object对象来调用wait方法,然后在Thread2中使用object去调用notify方法来唤醒线程调用wait方法的线程,当前代码的执行顺序的结果是:

线程Thread-0开始执行
线程Thread-1调用了notify()
线程Thread-0获取到了锁
1
2
3
这从另一个角度也证明了,wait是用来释放锁的。从上面的整个代码逻辑中,可以看出wait、notify、notifyAll被设计在Object类中的原因是,JAVA提供的锁是对象级的而不是线程级的,每个对象都有个锁,而线程是可以获得这个对象的。因此线程需要等待某些锁,那么只要调用对象中的wait()方法便可以了。而wait()方法如果定义在Thread类中的话,那么线程正在等待的是哪个锁就不明确了。这也就是说wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中是因为锁是属于对象的原因。

总结:
Wait-notify机制是在获取对象锁的前提下不同线程间的通信机制。在Java中,任意对象都可以当作锁来使用,由于锁对象的任意性,所以这些通信方法需要被定义在Object类里。

1.在java的内置锁机制中,每个对象都可以成为锁,也就是说每个对象都可以去调用wait,notify方法,而Object类是所有类的一个父类,把这些方法放在Object中,则java中的所有对象都可以去调用这些方法了。

2.一个线程可以拥有多个对象锁,wait,notify,notifyAll跟对象锁之间是有一个绑定关系的,比如你用对象锁Object调用的wait()方法,那么你只能通过Object.notify()或者Object.notifyAll()来唤醒这个线程,这样jvm很容易就知道应该从哪个对象锁的等待池中去唤醒线程,假如用Thread.wait(),Thread.notify(),Thread.notifyAll()来调用,虚拟机根本就不知道需要操作的对象锁是哪一个。

3.jvm允许锁定任意的对象,任意的对象也可以调用notify或notifyAll唤醒自己身上锁定的线程,按照面向对象的特性,wait,notify封装到Object里,可以提高代码的复用度,并且底层的实现细节我们也不需要去关心
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值