Thread之wait和notify

本文深入探讨Java中多线程通信的实现机制,重点讲解wait()和notify()方法的应用,对比sleep()方法的区别,以及如何正确使用这些方法进行线程间的同步与通信。

二者应用:多线程通信 (由boolean值、wait( )和notify( )构成了多线程通信)

wait()方法:

 用法:线程调用wait()方法,释放他对锁的拥有权,然后等待另外的线程来通知他
        (通知的方式是notify()或者notifyAll()方法),这样它才能重新获得所的拥有权和恢复执行

    作用:wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。
    限制条件:要确保wait()方法的时候拥有锁,即wait()方法的调用必须放在synchronized方法或者synchronized块中

    与sleep区别:    
        当线程调用wait()方法时,它会释放掉对象的锁,sleep()睡眠不会释放对象的锁的

notify()方法:
    作用:notify()会唤醒一个等待当前锁对象的线程。
    
    唤醒顺序: 如果多个线程在等待(只能唤醒wait方法等待的线程),他们中的一个将会选择被唤醒。这种选择是随意的(有jvm调度决定的)
          被唤醒的线程是不能被立即执行的,需要等到当前线程放弃这个对象的锁
   
    使用方法:notify()方法应该是被拥有对象的锁的线程所调用
    
    使用限制:notify方法调用和wait一样必须放在synchronized方法或synchronized块中,要求在调用时线程已经获得对象的锁

 被阻塞的线程和调用wait等待的线程:

  相同点:都经过锁定区

 其实等待区(调用wait睡眠的线程)的线程 ,在通过notify/notifyAll方法的调用之后是进入锁定区; 而 由于synchronized被阻塞的线程也是在锁定区

  不同点:"优先级"不同

  这两个根本就是一样的,虽然都是睡眠的线程,但是一个是在门里(屋内唤醒),一个是在门外(屋外唤醒);可以理解成被唤醒的线程优先级较高一些

  切记:能进入运行态的只有就绪态了。而就绪态是在获得锁之后才能进入,(所以被唤醒的线程不是立马进入就绪区,而是经过一次锁定区,因为他被唤醒后还得等,唤醒它的那个线程执行结束)

转载于:https://www.cnblogs.com/lm2-1/p/8491483.html

在Java多线程编程中,`wait()` `notify()` 是用于线程间通信的重要方法,它们定义在 `Object` 类中,并且必须在同步上下文中(如 `synchronized` 方法或代码块)中使用。这两个方法的主要作用是协调多个线程的执行顺序,确保线程之间可以安全地共享资源。 ### wait() 方法 `wait()` 方法的作用是使当前线程进入等待状态,直到其他线程调用该对象上的 `notify()` 或 `notifyAll()` 方法来唤醒它。调用 `wait()` 时,当前线程会释放持有的对象锁,并进入该对象的等待队列中[^4]。 一个典型的使用模式如下: ```java synchronized (lock) { while (!condition) { lock.wait(); } // 执行后续操作 } ``` 在此模式中,线程会在条件不满足时通过 `wait()` 进入等待状态,并在条件发生变化时被唤醒继续执行。 ### notify() 方法 `notify()` 方法用于唤醒在指定对象上等待的一个线程。如果有多个线程在等待,则由线程调度器随机选择其中一个进行唤醒。需要注意的是,调用 `notify()` 后,当前线程不会立即释放对象锁,而是要等到其所在的同步代码块或方法执行完毕后才会释放锁[^1]。 以下是一个简单的示例说明 `notify()` 的使用: ```java public class NotifyExample { public static void main(String[] args) { Object lock = new Object(); Thread t1 = new Thread(() -> { synchronized (lock) { System.out.println("t1 开始等待"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 被唤醒"); } }); Thread t2 = new Thread(() -> { synchronized (lock) { System.out.println("t2 准备通知"); lock.notify(); System.out.println("t2 已通知"); } }); t1.start(); try { Thread.sleep(1000); // 确保 t1 先进入等待状态 } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } ``` 在这个例子中,线程 `t1` 在进入同步代码块后调用 `wait()` 方法并释放锁,而线程 `t2` 在随后调用 `notify()` 来唤醒 `t1`。 ### 使用注意事项 - **必须在同步环境中使用**:`wait()` `notify()` 必须在 `synchronized` 方法或代码块中调用,否则会抛出 `IllegalMonitorStateException` 异常[^2]。 - **避免虚假唤醒**:通常建议将 `wait()` 放在一个循环中检查条件是否满足,以防止线程在没有收到通知的情况下被唤醒。 - **notify()notifyAll() 的区别**:`notify()` 只唤醒一个等待线程,而 `notifyAll()` 唤醒所有等待线程,适用于需要处理多个线程竞争的情况[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值