Java中的notyfy()和notifyAll()的本质区别

Java多线程编程中,我们经常会用到wait()、notify()和notifyAll()方法,它们都属于Object类中用于锁的方法。其中notify()和notifyAll()方法都是用来唤醒等待线程的方法,但它们在本质上是有一定区别的。

一、notify()和notifyAll()方法的作用

notify()和notifyAll()都用于唤醒当前对象上等待的线程,使其进入就绪状态,以便争夺对象锁并执行。它们都必须在同步块或同步方法中被调用。

notify()方法会随机唤醒当前对象中等待的一个线程,如果当前对象中有多个线程等待,那么哪个线程被唤醒是不确定的。因此,notify()方法常用于“生产者-消费者”模型中,当生产者往队列中放入一个元素后,只需要唤醒一个消费者线程进行消费即可。

notifyAll()方法会唤醒当前对象中等待的所有线程,这些线程将被全部放入就绪状态,线程调度程序随后会从这些线程中选择一个作为下一个执行线程。因此,notifyAll()方法常用于同步操作完成后唤醒所有等待的线程。

二、notify()和notifyAll()方法的区别

notify()方法和notifyAll()方法的本质区别在于唤醒等待线程的方式不同。notify()方法仅仅是唤醒任意一个等待线程,而notifyAll()方法会唤醒所有等待线程。因此,notify()方法存在线程竞争的问题,可能会导致一些线程永远都无法被唤醒。而notifyAll()方法虽然效率较低,但它可以确保所有的等待线程都能够被唤醒。

示例一:

public class NotifyTest implements Runnable {
    public synchronized void run() {
        System.out.println(Thread.currentThread().getName() + " begin to wait...");
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " has been notified...");
    }

    public static void main(String[] args) throws InterruptedException {
        NotifyTest notifyTest = new NotifyTest();
        Thread thread1 = new Thread(notifyTest, "Thread1");
        Thread thread2 = new Thread(notifyTest, "Thread2");
        Thread thread3 = new Thread(notifyTest, "Thread3");
        thread1.start();
        thread2.start();
        thread3.start();
        Thread.sleep(1000L);
        synchronized (notifyTest) {
            notifyTest.notify();
        }
    }
}

运行结果:

Thread1 begin to wait...
Thread2 begin to wait...
Thread3 begin to wait...
Thread1 has been notified...

在上面的示例中,我们创建了三个线程(Thread1、Thread2、Thread3),它们都调用notifyTest对象的wait()方法进行等待,然后主线程通过notify()方法唤醒对象上的一个线程。运行结果显示,只有Thread1被唤醒了,而Thread2和Thread3还在等待中,说明notify()方法只会唤醒其中的一个等待线程。

示例二:

public class NotifyAllTest implements Runnable {
    public synchronized void run() {
        System.out.println(Thread.currentThread().getName() + " begin to wait...");
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " has been notified...");
    }

    public static void main(String[] args) throws InterruptedException {
        NotifyAllTest notifyAllTest = new NotifyAllTest();
        Thread thread1 = new Thread(notifyAllTest, "Thread1");
        Thread thread2 = new Thread(notifyAllTest, "Thread2");
        Thread thread3 = new Thread(notifyAllTest, "Thread3");
        thread1.start();
        thread2.start();
        thread3.start();
        Thread.sleep(1000L);
        synchronized (notifyAllTest) {
            notifyAllTest.notifyAll();
        }
    }
}

运行结果:

Thread1 begin to wait...
Thread3 begin to wait...
Thread2 begin to wait...
Thread2 has been notified...
Thread1 has been notified...
Thread3 has been notified...

在上面的示例中,我们创建了三个线程(Thread1、Thread2、Thread3),它们都调用notifyAllTest对象的wait()方法进行等待,然后主线程通过notifyAll()方法唤醒对象上的全部等待线程。运行结果显示,所有的等待线程都被唤醒了,且唤醒的顺序是不确定的。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的notyfy()和notifyAll()的本质区别 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 记一次springboot中用undertow的坑

    记一次springboot中用undertow的坑 背景 在使用 Spring Boot 框架时,为了提高性能,可以选择使用 Undertow 作为 Web 容器。但是在实际应用中,使用 Undertow 可能会遇到一些坑。 问题 1. 配置路径匹配 使用 Undertow 时,如果需要配置路径匹配,需要在 application.properties 文件…

    Java 2023年5月19日
    00
  • iframe的各项参数整理附说明及使用示例

    iframe的各项参数整理附说明及使用示例 iframe是什么? iframe 全称是 Inline Frame,中文翻译为内联框架,是 HTML 的一种内嵌框架技术。通过它可以在网页中嵌入其它网页或者文档,可以说是一个在页面中嵌套显示其他 HTML 页面的容器。HTML 中真正的页面是父页面,iframe 中嵌套的是子页面。在父页面中,可以通过 ifram…

    Java 2023年6月16日
    00
  • Spring BeanPostProcessor源码示例解析

    Spring BeanPostProcessor源码示例解析 1. 什么是BeanPostProcessor? BeanPostProcessor是Spring框架中的一个扩展点,它允许我们在Bean实例化、依赖注入和初始化的过程中对Bean进行自定义处理。BeanPostProcessor接口定义了两个方法: Object postProcessBefor…

    Java 2023年5月18日
    00
  • 关于微信小程序获取小程序码并接受buffer流保存为图片的方法

    关于微信小程序获取小程序码并接受buffer流保存为图片的方法可以分为以下几步: 创建 API 方法 在小程序中,我们可以通过wx-api创建必要的API方法。这不仅可以帮助我们更好地组织代码,还可以使代码更具可读性和可维护性。 function getMiniProgramCode (path, width, callback) { wx.api.requ…

    Java 2023年5月23日
    00
  • SpringBoot在生产快速禁用Swagger2的方法步骤

    下面我将介绍使用SpringBoot在生产环境中快速禁用Swagger2的方法。 步骤一:pom.xml中排除Swagger2依赖 在pom.xml文件中,可以使用如下代码排除Swagger2依赖: <dependency> <groupId>io.springfox</groupId> <artifactId&gt…

    Java 2023年5月20日
    00
  • Java的Struts框架报错“NullActionFormException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“NullActionFormException”错误。这个错误通常由以下原因之一起: 表单对象为空:如果表单对象为空,则可能会出现此。在这种情况下,需要检查表单对象以解决此问题。 配置错误:如果配置文件中没有正确配置,则可能会出现此。在这种情况下,需要检查文件以解决此问题。 以下是两个实例: 例 1 如果表单对…

    Java 2023年5月5日
    00
  • SpringBoot应用的打包和发布实现

    打包和发布Spring Boot应用可以使用多种方法,下面是一些常见的方法: 方法一:使用Maven插件打包并上传到服务器 步骤一:使用Maven构建Spring Boot应用 在pom.xml文件中添加以下依赖: <!– 引入Spring Boot的pom依赖 –> <parent> <groupId>org.spr…

    Java 2023年5月19日
    00
  • 微信小程序实现表格前后台分页

    下面是微信小程序实现表格前后台分页的完整攻略: 1. 准备工作 安装微信开发者工具 新建小程序项目 安装 wx-server-sdk(用于云函数开发) 2. 前端页面设计 使用 table 标签展示表格 使用 navigator 标签实现分页 先给出一个示例代码: <view> <table> <thead> <tr…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部