Java多线程中wait、notify、notifyAll使用详解

Java多线程中wait、notify、notifyAll使用详解

简介

Java多线程提供了三个关键字:wait, notifynotifyAll,这三个关键字主要用于线程间的协调与通信,可有效避免线程之间产生相互干扰和互斥的问题。本章节主要对这三个关键字的使用进行详细讲解。

wait方法

语法格式

下面是wait方法的语法格式:

public final void wait() throws InterruptedException
public final native void wait(long timeout) throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException

该方法调用会将当前线程置入“等待池”中,并释放当前线程所持有的锁。直到获得了调用该方法的对象的锁定,并将该线程移出“等待池”。

示例说明

下面是一个简单的示例说明:

public static void main(String[] args) {
    final Object obj = new Object();
    Thread t1 = new Thread(() -> {
        synchronized(obj) {
            try { 
                System.out.println(Thread.currentThread().getName() + "开始执行");
                obj.wait();
                System.out.println(Thread.currentThread().getName() + "重新获得锁");
            } 
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    Thread t2 = new Thread(() -> {
        synchronized(obj) {
            System.out.println(Thread.currentThread().getName() + "开始执行");
            obj.notify();
            System.out.println(Thread.currentThread().getName() + "结束执行");
        }
    });

    t1.start();
    t2.start();
}

运行结果:

Thread-0开始执行
Thread-1开始执行
Thread-1结束执行
Thread-0重新获得锁

在这个例子中,我们创建了两个线程t1t2,线程t1先执行并尝试持有锁,然后调用wait()方法进入等待池中,释放锁资源。线程t2执行,并持有锁,然后调用notify()方法唤醒等待池中的线程t1。线程t1被唤醒并重新获得锁,输出结果。

notify方法

语法格式

下面是notify方法的语法格式:

public final native void notify()

该方法调用会唤醒在此对象监视器上等待的单个线程。

示例说明

下面是一个简单的示例说明:

public static void main(String[] args) {
    final Object obj = new Object();
    Thread t1 = new Thread(() -> {
        synchronized(obj) {
            try { 
                System.out.println(Thread.currentThread().getName() + "开始执行");
                obj.wait();
                System.out.println(Thread.currentThread().getName() + "重新获得锁");
            } 
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    Thread t2 = new Thread(() -> {
        synchronized(obj) {
            System.out.println(Thread.currentThread().getName() + "开始执行");
            obj.notify();
            System.out.println(Thread.currentThread().getName() + "结束执行");
        }
    });

    t1.start();
    t2.start();
}

运行结果:

Thread-0开始执行
Thread-1开始执行
Thread-1结束执行
Thread-0重新获得锁

在这个例子中,我们创建了两个线程t1t2,线程t1先执行并尝试持有锁,然后调用wait()方法进入等待池中,释放锁资源。线程t2执行,并持有锁,然后调用notify()方法唤醒等待池中的线程t1。线程t1被唤醒并重新获得锁,输出结果。

notifyAll方法

语法格式

下面是notifyAll方法的语法格式:

public final native void notifyAll()

该方法调用会唤醒在此对象监视器上等待的所有线程。

示例说明

下面是一个简单的示例说明:

public static void main(String[] args) {
    final Object obj = new Object();
    Thread t1 = new Thread(() -> {
        synchronized(obj) {
            try { 
                System.out.println(Thread.currentThread().getName() + "开始执行");
                obj.wait();
                System.out.println(Thread.currentThread().getName() + "重新获得锁");
            } 
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    Thread t2 = new Thread(() -> {
        synchronized(obj) {
            System.out.println(Thread.currentThread().getName() + "开始执行");
            obj.notifyAll();
            System.out.println(Thread.currentThread().getName() + "结束执行");
        }
    });

    t1.start();
    t2.start();
}

运行结果:

Thread-0开始执行
Thread-1开始执行
Thread-1结束执行
Thread-0重新获得锁

在这个例子中,我们创建了两个线程t1t2,线程t1先执行并尝试持有锁,然后调用wait()方法进入等待池中,释放锁资源。线程t2执行,并持有锁,然后调用notifyAll()方法唤醒等待池中的所有线程。线程t1被唤醒并重新获得锁,输出结果。

注意事项

  • 这三个关键字必须在同步语句块中使用,否则会抛出IllegalMonitorStateException异常。

  • wait()方法释放锁资源,线程进入等待池中,可以被其他线程唤醒。

  • notify()方法唤醒一个等待池中被调用wait()方法的线程,如果有多个线程等待,则随机唤醒其中之一。

  • notifyAll()方法唤醒所有等待池中被调用wait()方法的线程,这些线程将竞争锁资源。

总结

本章节是Java多线程中三个关键字wait, notifynotifyAll的使用详解,这三个关键字的正确使用方式在线程协调与通信等方面有着重要的作用。在实际开发中,需要注意这三个关键字的使用场景及注意事项,以保证程序的正确性和可靠性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程中wait、notify、notifyAll使用详解 - Python技术站

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

相关文章

  • JDK 7 新特性小结实例代码解析

    JDK 7 新特性小结实例代码解析 简介 JDK 7 是 Java Development Kit 的版本号,是 Java 的一个版本。JDK 7 主要添加了许多新特性,包括小型语言改进、文件访问/输入和输出的 I/O 改进、内部脚本引擎、实例创建类型推断、字符串开头的结尾和 switch 语句中的字符串变量、数字下划线等。本文将从例子出发,详细地介绍 JD…

    C 2023年5月23日
    00
  • C Primer Plus (7.12) 編程練習

    /*C Primer Plus (7.11) 3*/ 1 #include<stdio.h> 2 int main() 3 { 4 double weight,height; 5 printf(“Please enter your weight and height.\n”); 6 printf(“Weight (pound):”); 7 sca…

    C语言 2023年4月18日
    00
  • 抖音号认证蓝v有啥用?抖音蓝v认证优劣势分析

    抖音号认证蓝v有啥用? 抖音号认证蓝v可获得相应的认证标识,标识用户身份的真实性和权威性,提高用户公信力,也方便用户在大众中脱颖而出。那么抖音蓝v认证具体有哪些优劣势呢?接下来从以下几个方面进行分析。 优势 增强公信力 获得抖音蓝v认证的用户可以通过认证标识证明用户身份的真实性和权威性,这有助于提高用户公信力。 提高曝光率 相对于非认证用户,抖音认证用户具有…

    C 2023年5月22日
    00
  • Shell脚本实现C语言代码行数统计

    我们来详细讲解一下“Shell脚本实现C语言代码行数统计”的完整攻略。 1. Shell脚本实现C语言代码行数统计的思路 我们知道,C语言是一种编译型语言,编译后的代码是二进制可执行文件。想要统计C语言代码行数,我们需要将源代码文件解析成文本文件,然后使用Shell脚本进行行数统计。 具体步骤如下: 使用find命令查找指定目录下的所有.c和.h文件,并将文…

    C 2023年5月24日
    00
  • 详解C++中的this指针与常对象

    详解C++中的this指针与常对象 在C++类中,this指针是一个非常重要的概念。在本文中,我们将详细讲解this指针与常对象的概念、语法以及使用方法。 一、 this指针的概念 this指针是一个隐含的指针,它指向当前对象。在C++类中,每个非静态成员函数都有一个this指针,它可以访问当前对象的成员变量和成员函数。 二、 this指针的语法 在C++类…

    C 2023年5月22日
    00
  • 将代码中的调试信息输出到日志文件中

    一、将调试信息输出到屏幕中 1.1 一般写法 我们平常在写代码时,肯定会有一些调试信息的输出: #include <stdio.h> #include <stdlib.h> int main() { char szFileName[] = “test.txt”; FILE *fp = fopen(szFileName, “r”); i…

    C语言 2023年4月17日
    00
  • C语言实现设备管理系统

    C语言实现设备管理系统 1. 设备管理系统需求分析 管理员可以添加设备信息 管理员可以删除设备信息 管理员可以修改设备信息 系统可以显示设备信息 2. 设备管理系统设计 2.1 设备信息结构体 typedef struct device { int id; char name[20]; char type[20]; int quantity; float p…

    C 2023年5月23日
    00
  • 一篇文章带你顺利通过Python OpenCV入门阶段

    一篇文章带你顺利通过Python OpenCV入门阶段 介绍 Python是一种非常流行的编程语言,而OpenCV则是一个常用的计算机视觉库。结合它们,可以开发出许多强大的图像处理工具和算法。本篇文章将带领你了解Python OpenCV的入门阶段,帮助你熟悉如何使用Python OpenCV进行图像处理。 环境设置 在开始使用Python OpenCV之前…

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