多线程通信的三大法器,你真的会用吗?

简介: wait, notify, notifyAll 是多线程之间通信最重要的 3 个方法,今天,栈长给大家普及一下它们的知识要点及应用实战。

wait, notify, notifyAll 是多线程之间通信最重要的 3 个方法,今天,栈长给大家普及一下它们的知识要点及应用实战。


定义

wait:让持有该对象锁的线程等待;


notify: 唤醒任何一个持有该对象锁的线程;


notify: 唤醒所有持有该对象锁的线程;


它们 3 个的关系是,调用对象的 wait 方法使线程暂停运行,通过 notify/ notifyAll 方法唤醒调用 wait 暂时的线程。


然而,它们并不是 Thread 类中的方法,而是 Object 类中的,为什么呢!? 因为每个对象都有监视锁,线程要操作某个对象当然是要获取某个对象的锁了,而不是线程的锁。




如图所示,wait 带时间表示最大超时时间,过了时间还不唤醒就会自动唤醒线程重新竞争对象锁。


几个重要的点

1、调用对象的 wait, notify, notifyAll 方法需要拥有对象的监视器锁,即它们只能在同步方法(块)中使用;


2、调用 wait 方法会使用线程暂停并让出 CPU 资源,同时释放持有的对象的锁;


3、多线程使用 notify 容易发生死锁,一般使用 notifyAll;


4、关于 wait 和 sleep 的详细区别请翻阅 《多线程 sleep 和 wait 的 5 个区别》这篇文章。


实战

/**
 * 微信公众号:Java技术栈
 */
public static void main(String[] args) {
  Object lock = new Object();
  Thread t1 = new Thread(() -> {
    synchronized (lock) {
      for (int i = 0; i < 20; i++) {
        System.out.print(i);
        if (i == 10) {
          try {
            lock.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  });
  Thread t2 = new Thread(() -> {
    synchronized (lock) {
      try {
        Thread.sleep(5000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.print("Java技术栈");
      lock.notifyAll();
    }
  });
  t1.start();
  t2.start();
}

上面的例子结合 wait/ notifyAll 来演示了它们的相互作用。

线程 t1 首先输出 012345678910,5秒后继续输出 Java技术栈111213141516171819

相关文章
|
3月前
|
Java
实现Java多线程中的线程间通信
实现Java多线程中的线程间通信
|
4月前
|
Java 程序员
从菜鸟到大神:JAVA多线程通信的wait()、notify()、notifyAll()之旅
【6月更文挑战第21天】Java多线程核心在于wait(), notify(), notifyAll(),它们用于线程间通信与同步,确保数据一致性。wait()让线程释放锁并等待,notify()唤醒一个等待线程,notifyAll()唤醒所有线程。这些方法在解决生产者-消费者问题等场景中扮演关键角色,是程序员从新手到专家进阶的必经之路。通过学习和实践,每个程序员都能在多线程编程的挑战中成长。
44 6
|
4月前
|
Java
Java Socket编程与多线程:提升客户端-服务器通信的并发性能
【6月更文挑战第21天】Java网络编程中,Socket结合多线程提升并发性能,服务器对每个客户端连接启动新线程处理,如示例所示,实现每个客户端的独立操作。多线程利用多核处理器能力,避免串行等待,提升响应速度。防止死锁需减少共享资源,统一锁定顺序,使用超时和重试策略。使用synchronized、ReentrantLock等维持数据一致性。多线程带来性能提升的同时,也伴随复杂性和挑战。
81 0
|
4月前
|
安全 Java
JAVA多线程通信新解:wait()、notify()、notifyAll()的实用技巧
【6月更文挑战第20天】Java多线程中,`wait()`, `notify()`和`notifyAll()`用于线程通信。在生产者-消费者模型示例中,它们确保线程同步。`synchronized`保证安全,`wait()`在循环内防止虚假唤醒,`notifyAll()`避免唤醒单一线程问题。关键技巧包括:循环内调用`wait()`,优先使用`notifyAll()`以保证可靠性,以及确保线程安全和正确处理`InterruptedException`。
41 0
|
2月前
|
存储 安全 Java
【多线程面试题 七】、 说一说Java多线程之间的通信方式
Java多线程之间的通信方式主要有:使用Object类的wait()、notify()、notifyAll()方法进行线程间协调;使用Lock接口的Condition的await()、signal()、signalAll()方法实现更灵活的线程间协作;以及使用BlockingQueue作为线程安全的队列来实现生产者和消费者模型的线程通信。
|
4月前
|
Java 开发者
线程通信的方法和实现技巧详解
线程通信的方法和实现技巧详解
|
3月前
|
Java
实现Java多线程中的线程间通信
实现Java多线程中的线程间通信
|
3月前
|
消息中间件 安全 Java
Java中的线程间通信详解
Java中的线程间通信详解
|
3月前
|
消息中间件 Python
线程通信
【7月更文挑战第1天】
28 2
|
3月前
|
Java
线程间通信的几种方法
线程间通信的几种方法