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日

相关文章

  • C语言 strlen()函数

    当我们需要获取一个字符串的长度时,可以使用C语言中的 strlen() 函数。下面是该函数的完整使用攻略: 函数原型 size_t strlen(const char *str); 函数参数 str:要计算长度的字符串。必须为C风格的字符串,以\0结尾。 函数返回值 函数返回值为该字符串的长度,不包括\0。 使用示例一 下面是一个简单的示例,展示如何使用 s…

    C 2023年5月9日
    00
  • C语言实现散列表(哈希Hash表)实例详解

    下面我将为您详细讲解“C语言实现散列表(哈希Hash表)实例详解”的完整攻略。 概述 哈希(Hash)是一种能够快速定位存储位置的技术。哈希表(Hash Table)也叫散列表,是利用哈希函数(Hash Function)进行访问的数据结构。C语言中的哈希表主要分为两种:开放地址法和链表法。 开放地址法又分为线性探测法、二次探测法和双重散列法。本文主要介绍使…

    C 2023年5月23日
    00
  • C语言算法练习之数组求素数

    C语言算法练习之数组求素数 概述 本篇文章将介绍如何使用C语言实现数组求素数的算法。素数,又称质数,是指除了1和它本身以外,不能被其他自然数整除的正整数。本篇文章的算法流程如下:输入一个正整数n,计算出小于等于n的所有素数,将它们存储在一个数组中,并输出这些素数。该算法将使用C语言实现。 算法实现 1. 定义函数 首先,我们需要定义一个函数来计算小于等于n的…

    C 2023年5月22日
    00
  • CDR怎么绘制一个简单的工作证?

    下面是CDR(CorelDRAW)怎么绘制一个简单的工作证的完整攻略: 1. 准备工作 首先,我们需要打开CDR软件,创建一个新的文档。在创建文档的时候,我们需要选择“页面尺寸”和“页面方向”,通常我们可以选择A4纵向的页面尺寸。 2. 绘制证件模板 接下来,我们需要绘制一个证件的矩形框架作为证件的模板。首先,我们需要选择矩形工具(快捷键F6),在画布上绘制…

    C 2023年5月23日
    00
  • C++中stack的pop()函数返回值解析

    下面是关于C++中stack的pop()函数返回值解析的详细攻略。 什么是stack stack(栈)是一种线性结构,具有后进先出(LIFO)的特点,即最后入栈的元素最先出栈。C++中的STL库提供了stack容器,可以方便地实现栈的功能。 pop()函数 pop()函数是stack中用于弹出栈顶元素的函数,执行该函数后,栈顶的元素会被弹出,栈的大小会减小1…

    C 2023年5月22日
    00
  • 如何取消.net后台线程的执行

    如何取消.NET后台线程的执行 在开发.NET中常常需要使用后台线程实现任务的异步执行。但是有时候需要在任务执行期间取消线程的执行,以下是.NET中取消后台线程的方法。 CancellationTokenSource CancellationTokenSource可以用来取消线程执行,在需要取消执行的时候调用CancellationTokenSource.C…

    C 2023年5月23日
    00
  • 神乐千鹤在拳皇97、98中的高级用法

    神乐千鹤在拳皇97、98中的高级用法攻略 什么是神乐千鹤? 神乐千鹤是拳皇系列游戏中的一位角色,拥有快速的移动速度和敏捷的攻击方式。她在拳皇97和98中的操作难度较高,但是如果掌握了她的高级用法,就可以轻松地击败对手。 神乐千鹤的高级用法 1. 投掷连击 神乐千鹤的投掷连击是一种非常强大的攻击方式。要进行投掷连击,首先需要进行一次投掷攻击(按下前+C),然后…

    C 2023年5月22日
    00
  • C++11实现简易定时器的示例代码

    下面是关于“C++11实现简易定时器的示例代码”的完整攻略。 标题 C++11实现简易定时器的示例代码 简介 在开发事件驱动或多线程程序时,经常需要一种定时器来控制任务的执行时间。本篇攻略将介绍如何使用C++11编写一个简易的定时器,以此来满足我们在各种场景中的需求。 本攻略将包含两个实例展示如何使用简易定时器,读者可以通过这两个实例学习如何将其应用于自己的…

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