JavaEE语法第二章之多线程(初阶四)

news2024/11/26 10:42:15

一、wait 和 notify

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

球场上的每个运动员都是独立的 "执行流" , 可以认为是一个 "线程".
而完成一个具体的进攻得分动作, 则需要多个运动员相互配合, 按照一定的顺序执行一定的动作, 线程1 先 "传球" , 线程2 才能 "扣篮".

完成这个协调工作, 主要涉及到三个方法

  • wait() / wait(long timeout): 让当前线程进入等待状态.
  • notify() / notifyAll(): 唤醒在当前对象上等待的线程.

注意: wait, notify, notifyAll 都是 Object 类的方法.

 

1.1wait()方法

wait 做的事情:

  • 使当前执行代码的线程进行等待. (把线程放到等待队列中)
  • 释放当前的锁
  • 满足一定条件时被唤醒, 重新尝试获取这个锁.

wait 要搭配 synchronized 来使用. 脱离 synchronized 使用 wait 会直接抛出异常.

wait 结束等待的条件:

  • 其他线程调用该对象的 notify 方法.
  • wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
  • 其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.

代码示例: 观察wait()方法使用

public class ThreadDemo15 {
    public static void main(String[] args) throws InterruptedException{
        Object object=new Object();
        System.out.println("wait之前");
        synchronized(object){
            //加锁对象必须与wait对象相同
            object.wait();
        }

        System.out.println("wait之后");
    }
}

这样在执行到object.wait()之后就一直等待下去,那么程序肯定不能一直这么等待下去了。这个时候就需要使用到了另外一个方法唤醒的方法notify()。

1.2notify()方法

notify 方法是唤醒等待的线程.

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

代码示例: 使用notify()方法唤醒线程

public class ThreadDemo16 {
    public static void main(String[] args) throws InterruptedException{
        Object locker=new Object();
        Thread t1=new Thread(()->{
            try{
                System.out.println("wait开始");
                synchronized (locker){
                    locker.wait();
                }
                System.out.println("wait结束");
            }
            catch(InterruptedException e){
                e.printStackTrace();
            }
        });
        t1.start();
        Thread.sleep(1000);

        Thread t2=new Thread(()->{
           synchronized (locker){
               System.out.println("notify开始");
                locker.notify();
               System.out.println("notify结束");
           }
        });
        t2.start();
    }
}

1.3notifyAll()方法

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

范例:使用notifyAll()方法唤醒所有等待线程, 在上面的代码基础上做出修改.

static class WaitTask implements Runnable {
    // 代码不变
}
static class NotifyTask implements Runnable {
    // 代码不变
}
public void run() {
    synchronized (locker) {
        System.out.println("notify 开始");
        locker.notifyAll();
        System.out.println("notify 结束");
    }
}
public static void main(String[] args) throws InterruptedException {
    Object locker = new Object();
    Thread t1 = new Thread(new WaitTask(locker));
    Thread t3 = new Thread(new WaitTask(locker));
    Thread t4 = new Thread(new WaitTask(locker));
    Thread t2 = new Thread(new NotifyTask(locker));
    t1.start();
    t3.start();
    t4.start();
    Thread.sleep(1000);
    t2.start();
}

注意: 虽然是同时唤醒 3 个线程, 但是这 3 个线程需要竞争锁. 所以并不是同时执行, 而仍然是有先有后的执行.

理解 notify 和 notifyAll

notify 只唤醒等待队列中的一个线程. 其他线程还是乖乖等着

notifyAll 一下全都唤醒, 需要这些线程重新竞争锁

1.4wait 和 sleep 的对比(面试题)

其实理论上 wait 和 sleep 完全是没有可比性的,因为一个是用于线程之间的通信的,一个是让线程阻塞一段时间,唯一的相同点就是都可以让线程放弃执行一段时间.
当然为了面试的目的,我们还是总结下:
1. wait 需要搭配 synchronized 使用. sleep 不需要.
2. wait 是 Object 的方法 sleep 是 Thread 的静态方法. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/720619.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构课程设计系列】农夫过河问题操作演示

农夫过河 1、题目要求 1.1设计目的 掌握广度优先搜索策略,并用队列求解农夫过河问题。 1.2设计内容 一个农夫带着一只狼、一只羊和一棵白菜,身处和的南岸,他要把这些东西全部运到北岸,遗憾的是他只有一只小船,小船只能…

从小白到大神之路之学习运维第53天--------tomcat-web应用——————供开发的商城框架

第三阶段基础 时 间:2023年7月5日 参加人:全班人员 内 容: Tomcat应用服务 WEB服务 目录 实验环境:(四台服务器) 安装tomcat服务: NginxTomcat 负载均衡集群部署: 安装ng…

【JavaWeb基础】分层解耦

一、知识点整理 1、IOC与DI入门 1)控制反转: Inversion 0f Control,简称I0C。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。 2)依赖注入: Dependency lnjection,简称DI。容器为应用程序提供运…

vue 访问第三方 跨域, 配置vue.config.js

目录 0 config 文件被修改 一个要重启vscode 配置文件才会生效 1 第一种 (有两种写法) 1.1 配置vue.config.js 1.2 axios 使用 1.3 终端打印 2 第二种方法 --> 错误 --> 没有运行成功 2.1 配置vue.config.js --> 就是api 不被设置成 替换为 / 2.2 axios 使用…

【Linux初阶】理解一切皆文件 文件属性结构体底层 引用记数

🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【Linux初阶】 ✒️✒️本篇内容:理解一切皆文件,文件属性结构体底层理解(struct file、引用记数) &#x1…

记一次被通报的挖矿事件应急响应

为方便您的阅读,可点击下方蓝色字体,进行跳转↓↓↓ 01 事件背景介绍02 定位挖矿主机03 挖矿主机分析04 入侵路径梳理05 安全加固建议 01 事件背景介绍 某单位被上级单位通报,单位的出口IP和境外IP有异常通信行为,要求进行紧急处置…

【MySQL】何为MySQL,一文告诉你答案

文章目录 前言Oracle(甲骨文公司)MySQL关系型数据库应用环境特性 前言 在认识JAVA一文中我们有谈到过收购Sun公司的Oracle(甲骨文公司)1,今天我们要介绍的MySQL就属于 Oracle 旗下产品。 Oracle(甲骨文公司…

远航汽车:坚持合作共赢经营理念 携手志同道合者共创美好未来

智能汽车时代,想要打造一款真正符合用户需求的新能源车,势必要具备硬核技术实力以及敢于突破、不断求变的思维,始终做到以用户为中心,打造属于自己的品牌核心力,才能从激烈的市场竞争中脱颖而出。在此背景下&#xff0…

【电路原理学习笔记】第2章:电压、电流和电阻:2.6 电路

第2章:电压、电流和电阻 2.6 电路 2.6.1 电流的方向 电流方向有两种说法,一种按电子流动方向,另一种是传统的认为从正极流出到负极,这本教材采用传统电流方法。(事传统派,维新派输了,1&#…

全新QQ架构的“NT”版来袭

最近,全新发布的"NT"架构的QQ迎来了更新,同时面向用户开放了下载渠道,有些用户戏称为NT为脑瘫版本(bushi)苏音体验了以后,描述为:清爽简约还很流畅。 先来看看原来的QQ与现在的NT版本…

【Linux】Selinux基本了解

文章目录 SElinux1.简介2.基本概念3.规则4.策略5.工作模式 SElinux 1.简介 SELinux是一个内核级别的安全机制,从Linux2.6内核之后就将SELinux集成在了内核当中。因为SELinux是内核级别的,所以我们对于其配置文件的修改都是需要重新启动操作系统才能生效…

仿真模拟-Abaqus2021、Abaqus2022 安装下载教程

ABAQUS 是一套功能强大的工程模拟的有限元软件,其解决问题的范围从相对简单的线性分析到许多复杂的非线性问题。 ABAQUS 包括一个丰富的、可模拟任意几何形状的单元库。并拥有各种类型的材料模型库,可以模拟典型工程材料的性能,其中包括金属、…

Addressable 资源管理全解

这里写目录标题 一、什么是Addresables二、导入Addressables三、创建Addressables Settings 资产包管理四、资源集合Group的基本操作(资源分包)五、设置远程资源包六、如何打包七、加载方式7-1. Mono脚本指定和实例化:7-2. 直接实例化指定物体…

Neo4j docker 部署

想要运行简单测试一下neo4j,就直接使用docker创建了一个容器,并用cypher-shell本地连接neo4j,创建图进行测试。 1 开启docker sudo systemctl start docker2 拉取镜像源 sudo docker pull neo4j # 默认latest版本3 查看本地镜像&#xff0…

二叉树之按之字形顺序打印二叉树

主要看队列的应用与了解,就是利用先进先出的特点。先把每个节点塞入队列,再根据先进先出的特点来把自身值传入一维vector数组中去。 /*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(int x) : val(x), l…

作为爬虫工程师,自动化和抓包你说不了解的selenium采集内容篇!

前言 作为爬虫工程师,掌握Selenium采集是非常有用的,因为有些网站采用了动态加载、javascript渲染或AJAX技术,这些技术使得使用传统的静态HTML解析库难以获取到完整的数据。Selenium是一个自动化测试工具,它可以模拟用户在浏览器…

java特征:多态性

文章目录 多态的形式和体现对象的多态性多态的理解举例**1、方法内局部变量的赋值体现多态****2、方法的形参声明体现多态****3、方法返回值类型体现多态** 成员变量没有多态性向上转型与向下转型为什么要类型转换如何向上或向下转型instanceof关键字 多态的形式和体现 对象的…

【电路原理学习笔记】第2章:电压、电流和电阻:2.4 电流

第2章:电压、电流和电阻 2.4 电流 电压为电子提供能量,使它们能够在电路中运动。在金属导体中,电子的运动就是电流,电流的存在意味着在电路中存在着做功的过程。 自由电子存在于导体和半导体中。这些价电子层上的电子可以从材料…

微信小程序数据绑定及渲染

微信开发文档&#xff1a;WXML | 微信开放文档 (qq.com) 数据绑定 简单数据绑定 小程序原生支持数据的双向绑定&#xff0c;在wxml文件里面可以使用 Mustache 语法(双{{ }}方法)绑定js文件中data里面的属性 示例&#xff1a; wxml文件内容&#xff1a; <view> {{ mess…

ChromaVerse专注于AIGC元宇宙产业

在元宇宙与互联网 3.0 概念的推动下&#xff0c;各种虚拟数字人扑面而来&#xff0c;AIGC 产业成为各方关注的重点。未来 AI 发展已经成为全球科技领域的热点和趋势。AI 技术的快速进步和广泛应用正在改变人们的生活和工作方式&#xff0c;为各行各业带来了巨大的机遇和挑战。在…