IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 线程通讯(wait方法、notify方法、notifyAll方法) -> 正文阅读

[Java知识库]线程通讯(wait方法、notify方法、notifyAll方法)

目录

1. 方法介绍

2. wait使用

3. notify使用

4. notifyAll使用

5. 注意事项


由于线程之间是抢占式执?的, 因此线程之间执?的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执?先后顺序.

1. 方法介绍

完成这个协调?作( 线程通讯 ),主要涉及到三个?法:
??????? ?● wait() / wait(long timeout):让当前线程进?等待状态。
????????● notify():唤醒当前对象上?个休眠的线程(随机)。
????????● notifyAll():唤醒当前对象上的所有线程。
注意这三个?法都需要配合 synchronized ?起使?
这三个方法Object的内置方法,对象级别。

?

2. wait使用

?

wait 执?流程:
??●?使当前执?代码的线程进?等待. (把线程放到等待队列中)
??●?释放当前的锁(释放的是自己的锁)
??●?满??定条件时被唤醒, 重新尝试获取这个锁
wait 要搭配 synchronized 来使?. 脱离 synchronized 使? wait 会直接抛出异常.
? wait 结束等待的条件:
??●?其他线程调?该对象的 notify ?法.
??●?wait 等待时间超时 (wait ?法提供?个带有 timeout 参数的版本, 来指定等待时间).
??●?其他线程调?该等待线程的 interrupted ?法, 导致 wait 抛出 InterruptedException 异常.
wait使用:

public class WaitDemo {
    public static void main(String[] args) {
        Object lock = new Object();

        Thread t1 = new Thread(() -> {
            System.out.println("线程1开始执行");
            try {
                synchronized (lock) {
                    System.out.println("线程1调用wait方法....");
                    // 无限期的等待状态
                    lock.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程1执行完成");
        }, "线程1");
        t1.start();
    }
}

输出:
    线程1开始执行
    线程1调用wait方法....
(程序仍在执行)

?

3. notify使用

notify ?法是唤醒等待的线程:
??●??法notify()也要在同步?法或同步块中调?,该?法是?来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。
??●?如果有多个线程等待,则有线程调度器随机挑选出?个呈 wait 状态的线程。(并没有 "先来后到")
??●?在notify()?法后,当前线程不会?上释放该对象锁,要等到执?notify()?法的线程将程序执? 完,也就是退出同步代码块之后才会释放对象锁。

public class WaitDemo2 {
    public static void main(String[] args) {
        Object lock = new Object();
        Object lock2 = new Object();

        Thread t1 = new Thread(() -> {
            System.out.println("线程1开始执行");
            try {
                synchronized (lock) {
                    System.out.println("线程1调用wait方法....");
                    // 无限期的等待状态
                    lock.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程1执行完成");
        }, "线程1");


        Thread t2 = new Thread(() -> {
            System.out.println("线程2开始执行");
            try {
                synchronized (lock) {
                    System.out.println("线程2调用wait方法....");
                    // 无限期的等待状态
                    lock.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程2执行完成");
        }, "线程2");
        t2.start();
        t1.start();
        
        // 唤醒 lock 对象上休眠的线程的(随机唤醒一个)
        Thread t4 = new Thread(() -> {
            //先让线程1,2,3先执行
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
            }
            System.out.println("线程4:开始执行");
            synchronized (lock) {
                // 发出唤醒通知
                lock.notify();
                System.out.println("线程4:执行了唤醒操作");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                System.out.println("线程4:synchronized 执行完了");
            }
        }, "线程4");
        t4.start();

    }
}
输出:
    线程1开始执行
    线程2开始执行
    线程1调用wait方法....
    线程2调用wait方法....
    线程4:开始执行
    线程4:执行了唤醒操作
    线程4:synchronized 执行完了
    线程1执行完成

?

?

4. notifyAll使用

notify?法只是唤醒某?个等待线程. 使?notifyAll?法可以?次唤醒所有的等待线程。

public class WaitDemo3 {
    public static void main(String[] args) {
        Object lock = new Object();
        Object lock2 = new Object();

                Thread t1 = new Thread(() -> {
            System.out.println("线程1开始执行");
            try {
                synchronized (lock) {
                    System.out.println("线程1调用wait方法....");
                    // 无限期的等待状态
                    lock.wait();
                    System.out.println("线程1:恢复执行之后又进入休眠状态");
                    Thread.sleep(2000);
                    System.out.println("线程1执行完成");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1");

                Thread t2 = new Thread(() -> {
            System.out.println("线程2开始执行");
            try {
                synchronized (lock) {
                    System.out.println("线程2调用wait方法....");
                    // 无限期的等待状态
                    lock.wait();
                    System.out.println("线程2:恢复执行之后又进入休眠状态");
                    Thread.sleep(2000);
                    System.out.println("线程2执行完成");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程2");

                Thread t3 = new Thread(() -> {
            System.out.println("线程3开始执行");
            try {
                synchronized (lock) {
                    System.out.println("线程3调用wait方法....");
                    // 无限期的等待状态
                    lock.wait();
                    System.out.println("线程3:恢复执行之后又进入休眠状态");
                    Thread.sleep(2000);
                    System.out.println("线程3执行完成");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程3");
        t2.start();
        t1.start();
        t3.start();

        // 唤醒 lock 对象上休眠的线程的(随机唤醒一个)
        Thread t4 = new Thread(() -> {
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
            }
            System.out.println("线程4:开始执行");
            synchronized (lock) {
                // 发出唤醒通知
                lock.notifyAll();
                lock.notifyAll();
                System.out.println("线程4:执行了唤醒操作");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                System.out.println("线程4:synchronized 执行完了");
            }
        }, "线程4");
        t4.start();

    }
}
输出:
    线程2开始执行
    线程2调用wait方法....
    线程3开始执行
    线程1开始执行
    线程3调用wait方法....
    线程1调用wait方法....
    线程4:开始执行
    线程4:执行了唤醒操作
    线程4:synchronized 执行完了
    线程1:恢复执行之后又进入休眠状态
    线程1执行完成
    线程3:恢复执行之后又进入休眠状态
    线程3执行完成
    线程2:恢复执行之后又进入休眠状态
    线程2执行完成
修改线程3中的lock为lock2

try {
                synchronized (lock2) {
                    System.out.println("线程3调用wait方法....");
                    // 无限期的等待状态
                    lock2.wait();
                    System.out.println("线程3:恢复执行之后又进入休眠状态");
                    Thread.sleep(2000);
                    System.out.println("线程3执行完成");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

输出:
    线程2开始执行
    线程1开始执行
    线程3开始执行
    线程2调用wait方法....
    线程3调用wait方法....
    线程1调用wait方法....
    线程4:开始执行
    线程4:执行了唤醒操作
    线程4:synchronized 执行完了
    线程1:恢复执行之后又进入休眠状态
    线程1执行完成
    线程2:恢复执行之后又进入休眠状态
    线程2执行完成

?由上述两个代码可以得出,notifyAll 并不是唤醒所有的wait 等待的线程,而是唤醒当前对象处于wait 等待的所有线程。

5. 注意事项

????????1. wait / notify / notifyAll 必须要配合synchronized一起执行。
????????2. wait / notify / notifyAll 进行?synchronized 加锁,一定要使用同一个·对象进行加锁,不然会报错。
????????3. 当调用了notify /??notifyAll 之后,程序并不会立即恢复执行,而是尝试获取锁,只有得到锁之后才能继续执行。
? ? ? ? 4. notifyAll 并不是唤醒所有的wait 等待的线程,而是唤醒当前对象处于wait 等待的所有线程。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 11:57:15  更:2022-04-04 11:57:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:16:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码