当前位置: 首页 > news >正文

【Java多线程进阶】JUC常见类以及CAS机制

1. Callable的用法

之前已经接触过了Runnable接口,即我们可以使用实现Runnable接口的方式创建一个线程,而Callable也是一个interface,我们也可以用Callable来创建一个线程。

  • Callable是一个带有泛型的interface
  • 实现Callable接口必须重写call方法
  • call方法带有返回值,且返回值类型就是泛型类型
  • 可以借助FutureTask类接收返回值,更方便的帮助程序员完成计算任务并获取结果

下面我们来举一个案例,要求分别使用实现Runnable接口和Callable接口完成计算1+2+3+…1000并在主线程中打印结果的任务,体会区别。

1.1 使用Runnable接口

public class ThreadDemo01 {private static int result = 0;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 1000; i++) {result += i;}}});// 启动线程t.start();t.join();// 打印结果System.out.println("result: " + result); // 500500}
}

上述代码实现Runnable接口来启动一个线程,这段代码可以实现累加1-1000的任务,但是不够优雅!因为需要额外借助一个成员变量result来保存结果,当业务量繁多时,如果有多个线程完成各自的计算任务,那么就需要更多的成员变量保存结果,因此现在想想带有返回值的线程也许是有必要的!下面我们来看看如何使用Callable接口完成

1.2 使用Callable接口

public class ThreadDemo02 {public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int result = 0;for (int i = 1; i <= 1000; i++) {result += i;}return result;}};// 创建FutureTask实例FutureTask<Integer> futureTask = new FutureTask<>(callable);// 创建线程并启动Thread t = new Thread(futureTask);t.start();// 阻塞并获取返回结果int result = futureTask.get();System.out.println("result: " + result); // 500500}
}

上述代码中我们使用了实现Callable的方式完成任务,值得一提的是,Callable实现类对象不能直接作为Thread构造方法的参数,我们需要借助一个中间人即 FutureTask 类,该类实现了Runnable接口,因此可以直接作为Thread构造方法的参数。

注:futureTask.get()方法带有阻塞功能,直到子线程完成返回结果才会继续运行

1.3 如何理解FutureTask和Callable

理解Callable:1、Callable与Runnable是相对的,都是描述一个任务,Callable描述带有返回值的任务,Runnable描述不带返回值的任务。2、Callable往往需要搭配FutureTask一起使用,FutureTask用于保存Callable的返回结果,因为Callable中的任务往往在另一个线程执行,具体什么时候执行并不确定
理解FutureTask:FutureTask顾名思义就是未来任务,即Callable中的任务是不确定何时执行完毕的,我们可以形象描述为去杨国福吃麻辣烫时等待叫号,但是什么时候叫号是不确定的,通常点餐完毕后服务员会给一个取号凭证,我们可以凭借这个取号凭证查看自己的麻辣烫有没有做好。

1.4 相关面试题

  1. 介绍下Callable是什么?

2. 信号量Semaphore

相信大学期间修过操作系统课的小伙伴对semaphore这个单词并不陌生,这不就是OS的信号量机制可以实现PV操作的么?而JVM对OS提供的semaphore又进行了封装形成了Java标准库中的Semaphore
semaphore:信号量,用来表示可用资源的数目,本质上是一个计数器。

我们可以拿停车场的展示牌进行举例,当前留有空闲车位100个时,展示牌上就会显示100,表示可用资源的数目,当有汽车开进停车位时,相当于申请了一个可用资源,此时展示牌数目就会-1(称为信号量的P操作),当有汽车驶出停车位,相当于释放了一个可用资源,此时展示牌数目+1(称为信号量V操作)

Semaphore的信号量PV操作都是原子性的,可以直接在多线程环境中使用。

锁其实本质上就是特殊的信号量,加锁可以看作时信号量为0,解锁可以看作信号量为1,所以也有说法称"锁"其实是一个二元信号量,那么既然"锁机制"能够实现线程安全,信号量也可以用来保证线程安全!

2.1 Semaphore代码案例

Semaphore相关API:

  1. acquire:相当于P操作,申请一个可用资源
  2. release:相当于V操作,释放一个可用资源

代码举例:

  1. 创建Semaphore实例并初始化为4,表示有4个可用资源
  2. 创建20个线程,每个线程都尝试申请资源,sleep1秒后释放资源,观察程序运行状况
public class SemaphoreExample {public static void main(String[] args) {// 初始化信号量为4Semaphore semaphore = new Semaphore(4);// 创建20个线程for (int i = 0; i < 20; i++) {int id = i;Thread t = new Thread(() -> {try {semaphore.acquire(); // 申请资源System.out.println("线程" + id + "申请到了资源");Thread.sleep(1000); // 睡眠1ssemaphore.release(); // 释放资源System.out.println("线程" + id + "释放资源");} catch (InterruptedException e) {throw new RuntimeException(e);}});// 启动线程t.start();}}
}

执行结果
image.png
其中可以发现当前四个线程申请资源后,此时第五个线程尝试申请资源后,信号量变为-1就会阻塞等待,直到其他线程释放资源后才可以继续申请!

3. CountDownLatch的使用

CountDownLatch:可以等待N个任务全部完成。类似于N个人进行跑步比赛,直到最后一个人跃过终点才会宣布比赛结束,公布最后成绩。

3.1 CountDownLatch相关API

CountDownLatch提供API:

  1. new CountDownLatch(int n):构造方法,初始化n表示有n个任务需要完成
  2. countDown():任务执行完毕后调用,内部计数器进行自减
  3. await():阻塞等待所有任务全部完成后继续执行,相当于等待内部计数器为0

3.2 CountDownLatch代码案例

CountDownLatch代码案例:

  1. 创建10个线程,并初始化CountDownLatch为10
  2. 每个线程随机休眠1-5秒,模拟比赛结束
  3. 主线程中使用await阻塞等待全部执行完毕
public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {Random random = new Random();// 初始化CountDownLatch为10CountDownLatch latch = new CountDownLatch(10);// 创建10个线程for (int i = 0; i < 10; i++) {int curId = i;Thread t = new Thread(() -> {System.out.println("线程" + curId + "开始执行...");try {Thread.sleep(random.nextInt(6) * 1000);System.out.println("线程" + curId + "结束执行...");latch.countDown(); // 计数器自减} catch (InterruptedException e) {throw new RuntimeException(e);}});// 启动线程t.start();}// 阻塞等待全部执行完毕latch.await();System.out.println("全部任务执行完毕!");}
}

执行结果
image.png
此时我们可以看到调用countDownLatch.await()方法时只有当所有的线程都执行完毕,即调用10次countDown方法后(即内部计数器为0)时才会停止阻塞!

4. ReentrantLock类

ReentrantLock:位于java.util.concurrent包下,被称为可重入互斥锁,和synchronized定位类似,都是用来实现互斥效果的可重入锁,保证线程安全。

4.1 ReentrantLock的用法

ReentrantLock相关API:

  1. lock():尝试加锁,如果加锁失败就阻塞等待
  2. tryLock(超时时间):尝试加锁,获取不到就阻塞等待一定时间,超时则放弃加锁
  3. unlock():解锁

注意:由于ReentrantLock需要手动释放锁,因此常常把unlock方法放在finally块中

ReentrantLock lock = new ReentrantLock();
--------------  相关代码  --------------
lock.lock();
try {// do something...
} finally {lock.unlock();
}

4.2 ReentrantLock与synchronized的区别(经典面试题)

  1. synchronized是一个关键字,是JVM内部实现的(大概率使用C++语言实现),而ReentrantLock是一个标准库中提供的类,是在JVM外部实现的(基于Java实现)
  2. ReentrantLock使用lock和unlock一对方法进行手动加锁、解锁,相较于synchronized更加灵活,但是也容易遗漏释放锁的步骤。
  3. synchronized是非公平锁,而ReentrantLock默认是非公平锁,但是可以变成公平锁,只需要在构造方法中传入参数为true即可。
  4. ReentrantLock比synchronized具有更加精准的唤醒机制,synchronized使用Object类的wait/notify进行唤醒,随机唤醒一个等待线程,而ReentrantLock借助类Condition实现等待唤醒,可以精准控制唤醒某一个指定线程。

5. CAS机制

5.1 CAS的基本概念

CAS:全程为compare and swap字面意思就是比较并且交换,一个CAS涉及以下操作:

我们假设内存中的原数据为V,旧的预期值为A,需要修改的新值为B

  1. 比较A与V是否相等(比较)
  2. 如果比较相等则将B写入内存替换V(交换)
  3. 返回操作是否成功。

CAS伪代码:

public boolean CAS(address, expectValue, swapValue) {if (&address == expectValue) {&address = swapValue;return true;}return false;
}

注意:CAS是一个硬件指令,其操作是原子性的,这个伪代码只是辅助理解CAS的工作流程

对CAS原子性的理解:CAS可以看做是乐观锁的一种实现方式,当多个线程同时对某个资源进行CAS操作时,只要一个线程操作成功返回true,其余线程全部返回false,但是不会阻塞。

5.2 CAS的常见应用

5.2.1 实现原子类

标准库中提供了java.util.concurrent.atomic包,里面的类都是基于CAS的方式实现的,最典型的就是AtomicInteger类,其中的getAndIncrement方法相当于i++操作

AtomicInteger atomicInteger = new AtomicInteger(0);
// 相当于i++操作
atomicInteger.getAndIncrement();

下面是AtomicInteger类基于CAS方式的伪代码实现:

class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;while (CAS(value, oldValue, oldvalue + 1) != true) {oldValue = value;}return oldValue;}
}

5.2.2 实现自旋锁

基于CAS也可以实现更加灵活的锁,获取到更多的控制权
下面是基于CAS的自旋锁伪代码实现:

class SpinLock {private Thread owner;public void lock() {while (!CAS(owner, null, Thread.currentThread())) {}}public void unlock() {this.owner = null;}
}

5.3 CAS的ABA问题

5.3.1 ABA问题概述

什么是ABA问题:假设现在有两个线程共用一个共享变量num,初始值为A,此时线程t1,期望使用CAS机制将num值修改为Z,线程t1的CAS判定流程如下:

  • 如果此时num == A,那么就将内存中的num值修改为Z
  • 如果此时num != A,那么就不进行修改,重新判定

但是此时中间穿插了线程t2执行将num值修改为了B,但是又重新修改为了A,所以尽管t1线程比较的预期结果是一致的,但是很可能已经是别人的形状了!
image.png

ABA导致的问题

ABA问题有可能会导致严重的后果,比如说我去银行ATM机取钱,考虑采用的时CAS机制,目前我的账户余额为1500,我按下确定按钮想要取出500元钱,但是ATM机卡住了,因此我又按下一次确定按钮,此时正常情况如下:
正常情况
image.png
此时结果是符合预期的!扣款线程t1进行扣款操作,此时余额变为1000元,扣款线程t2判断当前余额已经不为1500了,说明已经扣款成功!于是不进行后续扣款操作!但是如果中间出现其他线程汇款操作,就会出现ABA问题,导致严重后果!
极端情况
image.png
此时扣款线程t1完成扣款操作后,余额变为1000,但是中间穿插了汇款线程t3,刚好往账户中存入金额500,此时扣款线程t3判断余额仍然为1500,因此又进行了多余的一次扣款操作!!!这是相当不合理的

5.3.2 ABA问题解决思路

为了解决ABA带来的问题,我们可以考虑使用 版本号 的思想解决:

  • CAS读取数据的时候,同时也要读取版本号
  • 如果当前版本号与读取版本号一致,修改数据同时将版本号+1
  • 如果当前版本号高于读取版本号,则说明数据已经被修改,当前操作非法

6. 线程安全的集合类

Java提供的集合类大部分都是线程不安全的

Vector,Stack,HashTable是线程安全的(但是官方不推荐使用)

6.1 多线程环境使用ArrayList

  1. 自己加锁(使用synchronized或者ReentrantLock实现)
  2. 使用Collections.synchronizedList,这是标准库提供的基于synchronized实现的线程安全的类,本质上是在关键方法上加了synchronized修饰
  3. 使用CopyOnWriteArrayList,这是一个借助写时拷贝机制实现的容器,常用于配置文件等不经常修改,占用内存较小等场景

写时拷贝机制的核心就是可以对原容器进行并发的读,涉及写操作则先对原容器进行拷贝,然后向新容器中添加元素,最后修改引用,实现了读写分离!

6.2 多线程环境使用队列

  1. 自己加锁实现(synchronized或者ReentrantLock实现)
  2. 使用标准库提供的BlockingQueue接口及其实现类

6.3 多线程环境使用哈希表

  1. 使用HashTable

    只是在关键方法上加上synchronized进行修饰

  2. ConcurrentHashMap(常考面试题)

    相比于Hashtable做出了一系列优化(以JDK1.8为例)

    • 优化方式一:读操作没有加锁,只有写操作才会加锁,加锁的方式仍然使用synchronized,但是并不是锁整个对象,而是锁"桶"(使用链表的头结点作为锁对象),大大降低了锁冲突的概率
    • 优化方式二:对于一些变量例如哈希表元素个数size,使用CAS机制避免重量级锁出现
    • 优化方式三:优化了扩容方式,采用"化整为零","蚂蚁搬家"的方式,扩容期间新老数组同时存在,一次搬运只搬运少量元素,因此新增操作只需要在新数组中插入即可,查询操作需要在新老数组同时查询,删除操作也需要新老数组同时删除

相关文章:

【Java多线程进阶】JUC常见类以及CAS机制

1. Callable的用法 之前已经接触过了Runnable接口&#xff0c;即我们可以使用实现Runnable接口的方式创建一个线程&#xff0c;而Callable也是一个interface&#xff0c;我们也可以用Callable来创建一个线程。 Callable是一个带有泛型的interface实现Callable接口必须重写cal…...

Python算法100例-1.7 最佳存款方案

完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1.问题描述2.问题分析3.算法设计4.完整的程序 1&#xff0e;问题描述 假设银行一年整存零取的月息为0.63%。现在某人手中有一笔钱&#xff0c;他打算在今后5年中的每年年底取出1000元&#xff0c;到第5年时刚…...

ADO世界之FIRST

目录 一、ADO 简介 二、ADO 数据库连接 1.创建一个 DSN-less 数据库连接 2.创建一个 ODBC 数据库连接 3.到 MS Access 数据库的 ODBC 连接 4.ADO 连接对象&#xff08;ADO Connection Object&#xff09; 三、ADO Recordset&#xff08;记录集&#xff09; 1.创建一个 …...

【COMP337 LEC 5-6】

LEC 5 Perceptron &#xff1a; Binary Classification Algorithm 8 感应器是 单个神经元的模型 突触连接的强度取决于接受外部刺激的反应 X input W weights a x1*w1x2*w2....... > / < threshold Bias MaxIter is a hyperparameter 超参数 which has to be chosen…...

力扣72. 编辑距离(动态规划)

Problem: 72. 编辑距离 文章目录 题目描述思路复杂度Code 题目描述 思路 由于易得将字符串word1向word2转换和word2向word1转换是等效的&#xff0c;则我们假定统一为word1向word2转换&#xff01;&#xff01;&#xff01; 1.确定状态&#xff1a;我们假设现在有下标i&#x…...

linux tree命令找不到:如何使用Linux Tree命令查看文件系统结构

Linux tree命令是一个用于显示文件夹和文件的结构的工具&#xff0c;它可以帮助用户更好地理解文件系统的结构。如果你在linux系统上找不到tree命令&#xff0c;那么可能是因为你的系统中没有安装tree命令。 解决方案 Linux tree命令是一个用于显示文件夹和文件的结构的工具&…...

OJ_最大逆序差

题目 给定一个数组&#xff0c;编写一个算法找出这个数组中最大的逆序差。逆序差就是i<j时&#xff0c;a[j]-a[i]的值 c语言实现 #include <stdio.h> #include <limits.h> // 包含INT_MIN定义 int maxReverseDifference(int arr[], int size) { if (size…...

MyBatis-Plus 实体类里写正则让字段phone限制为手机格式

/* Copyright © 2021User:啾啾修车File:ToupiaoRecord.javaDate:2021/01/12 19:29:12 */ package com.jjsos.repair.toupiao.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomido…...

K8S之运用污点、容忍度设置Pod的调度约束

污点、容忍度 污点容忍度 taints 是键值数据&#xff0c;用在节点上&#xff0c;定义污点&#xff1b; tolerations 是键值数据&#xff0c;用在pod上&#xff0c;定义容忍度&#xff0c;能容忍哪些污点。 污点 污点是定义在k8s集群的节点上的键值属性数据&#xff0c;可以决…...

Sora爆火,普通人的10个赚钱机会

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…...

【C++】C++入门—初识构造函数 , 析构函数,拷贝构造函数,赋值运算符重载

C入门 六个默认成员函数1 构造函数语法特性 2 析构函数语法特性 3 拷贝构造函数特性 4 赋值运算符重载运算符重载赋值运算符重载特例&#xff1a;前置 与 后置前置&#xff1a;返回1之后的结果后置&#xff1a; Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&…...

沁恒CH32V30X学习笔记04--外部中断

外部中断 CH32V2x 和 CH32V3x 系列内置可编程快速中断控制器(PFIC– Programmable Fast Interrupt Controller),最多支持 255 个中断向量。当前系统管理了 88 个外设中断通道和 8 个内核中断通道 PFIC 控制器 88个外设中断,每个中断请求都有独立的触发和屏蔽控制位,有专…...

基础IO[三]

close关闭之后文件内部没有数据&#xff0c; stdout和stderr 他们一起重定向&#xff0c;只会重定向号文件描述符&#xff0c;因为一号和二号描述符虽然都是sydout&#xff0c;但是并不一样&#xff0c;而是相当于一个显示器被打开了2次。 分别重定向到2个文件的写法和直接写道…...

Leetcode 392 判断子序列

题意理解&#xff1a; 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde&quo…...

基于微信小程序的校园跑腿系统的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

VTK Python PyQt 监听键盘 控制 Actor 移动 变色

KeyPressInteractorStyle 在vtk 中有时我们需要监听 键盘或鼠标做一些事&#xff1b; 1. 创建 Actor&#xff1b; Sphere vtk.vtkSphereSource() Sphere.SetRadius(10)mapper vtk.vtkPolyDataMapper() mapper.SetInputConnection(Sphere.GetOutputPort()) actor vtk.vtkAc…...

力扣 第 124 场双周赛 解题报告 | 珂学家 | 非常规区间合并

前言 整体评价 T4的dp解法没想到&#xff0c;走了一条"不归路", 这个区间合并解很特殊&#xff0c;它是带状态的&#xff0c;而且最终的正解也是基于WA的case&#xff0c;慢慢理清的。 真心不容易&#xff0c;太难了。 T1. 相同分数的最大操作数目 I 思路: 模拟 c…...

2024年华为OD机试真题-生成哈夫曼树-Java-OD统一考试(C卷)

题目描述: 给定长度为n的无序的数字数组,每个数字代表二叉树的叶子节点的权值,数字数组的值均大于等于1。请完成一个函数,根据输入的数字数组,生成哈夫曼树,并将哈夫曼树按照中序遍历输出。 为了保证输出的二叉树中序遍历结果统一,增加以下限制:二叉树节点中,左节点权…...

【实战】二、Jest难点进阶(二) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(六)

文章目录 一、Jest 前端自动化测试框架基础入门二、Jest难点进阶2.mock 深入学习 学习内容来源&#xff1a;Jest入门到TDD/BDD双实战_前端要学的测试课 相对原教程&#xff0c;我在学习开始时&#xff08;2023.08&#xff09;采用的是当前最新版本&#xff1a; 项版本babel/co…...

(一)【Jmeter】JDK及Jmeter的安装部署及简单配置

JDK的安装和环境变量配置 对于Linux、Mac和Windows系统,JDK的安装和环境变量配置方法略有不同。以下是针对这三种系统的详细步骤: 对于Linux系统: 下载适合Linux系统的JDK安装包,可以选择32位或64位的版本。 将JDK的安装包放置在服务器下,创建一个新的文件夹来存储JDK,…...

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例

HAL/LL/STD STM32 U8g2库 I2C SSD1306/sh1106 WouoUI磁贴案例 &#x1f4cd;基于STM32F103C8T6 LL库驱动版本&#xff1a;https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM&#x1f3ac;视频演示&#xff1a; WouoUI移植磁贴案例&#xff0c;新增确认弹窗 &#x1f…...

手机如何改自己的ip地址

在现如今的数码时代&#xff0c;手机已经成为人们生活中不可或缺的一部分。然而&#xff0c;有时候我们可能需要改变手机的IP地址来实现一些特定的需求。本文将向大家介绍如何改变手机的IP地址&#xff0c;帮助大家更好地应对各种网络问题。 更改手机IP地址的原因&#xff1a;…...

ajax函数库axios基本使用

ajax函数库Axios基本使用 简介&#xff1a;Axios 对原生的Ajax进行了封装&#xff0c;简化书写&#xff0c;快速开发。 官网&#xff1a;https://www.axios-http.cn/ Axios使用步骤 引入Axios的js文件(参考官网)使用Axios发送请求,获取相应结果 <script src"https:…...

【nginx实践连载-4】彻底卸载Nginx(Ubuntu)

步骤1&#xff1a;停止Nginx服务 打开终端&#xff08;Terminal&#xff09;。停止Nginx服务&#xff1a;sudo systemctl stop nginx步骤2&#xff1a;卸载Nginx软件包 运行以下命令卸载Nginx软件包&#xff1a;sudo apt purge nginx nginx-common nginx-core步骤3&#xff1…...

究极小白如何自己搭建一个自动发卡网站-独角数卡

首页 | 十画IOSID​shihuaid.cn/​编辑 如果你也是跟我一样,什么都不懂,也想要搭建一个自己的自动发卡网站,可以参考一下我的步骤,不难,主要就是细心,一步步来一定成功!! 独角数卡: 举个例子:独角数卡就是一个店面,而且里面帮你装修好了,而你要做的就是把开店之…...

Java_方法(重载方法签名等详解)

在之前我们学习C语言时&#xff0c;当我们想要重复使用某段代码的功能时&#xff0c;我们会将这段代码定义为一个函数&#xff0c;而在java中我们把这段重复使用的代码叫做方法。 方法的定义 类体的内容分为变量的声明和方法的定义&#xff0c;方法的定义包括两部分&#xff1…...

VQ35 评论替换和去除(char_length()和replace函数的使用)

代码 select id ,replace(comment,&#xff0c;,) as comment from comment_detail where char_length(comment)>3知识点 要注意替换的是中文逗号 由于题目说的是汉字长度大于3&#xff0c;所以这里就要使用char_length()而不是length() char_length()&#xff1a;单位为字…...

【MySQL】学习多表查询和笛卡尔积

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-N8PeTKG6uLu4bJuM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…...

RabbitMQ实现延迟消息的方式-死信队列、延迟队列和惰性队列

当一条消息因为一些原因无法被成功消费&#xff0c;那么这这条消息就叫做死信&#xff0c;如果包含死信的队列配置了dead-letter-exchange属性指定了一个交换机&#xff0c;队列中的死信都会投递到这个交换机内&#xff0c;这个交换机就叫死信交换机&#xff0c;死信交换机再绑…...

【运维测试】测试理论+工具总结笔记第1篇:测试理论的主要内容(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论测试理论测试工具相关知识。Python测试理论的主要内容&#xff0c;掌握软件测试的基本流程&#xff0c;知道软件测试的V和W模型的优缺点&#xff0c;掌握测试用例设计的要素&#xff0c;掌握等价类划分法、边界值法、因…...

【C语言】实现队列

目录 &#xff08;一&#xff09;队列 &#xff08;二&#xff09;头文件 &#xff08;三&#xff09; 功能实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09; 销毁队列 &#xff08;3&#xff09; 入队 &#xff08;4&#xff09;出队 &#xff08;5&a…...

【友塔笔试面试复盘】八边形取反问题

问题&#xff1a;一个八边形每条边都是0&#xff0c;现在有取反操作&#xff0c;选择一条边取反会同时把当前边和2个邻边取反&#xff08;如果是0变为1&#xff0c;如果是1变为0&#xff09; 现在问你怎么取反能使得八条边都变为1. 当时陷入了暴力递归漩涡&#xff0c;给出一个…...

GB 18585-2023 壁纸中有害物质限量

壁纸/墙布因其色彩多样&#xff0c;图案丰富&#xff0c;施工方便&#xff0c;价格便宜等多种优势&#xff0c;广泛应用于室内装修材料&#xff0c;在国内&#xff0c;日本&#xff0c;欧美等地区非常普及。 GB 18585-2023壁纸中有害物质限量测试项目&#xff1a; 测试项目 测…...

全面的ASP.NET Core Blazor简介和快速入门

前言 因为咱们的MongoDB入门到实战教程Web端准备使用Blazor来作为前端展示UI&#xff0c;本篇文章主要是介绍Blazor是一个怎样的Web UI框架&#xff0c;其优势和特点在哪&#xff1f;并带你快速入门上手ASP.NET Core Blazor(当然这个前提是你要有一定的C#编程基础的情况&#x…...

HGAME 2024 WEEK2 Crypto WP

前言 我很菜&#xff0c;有没做出来的题目&#xff0c;带*号题为复现。 midRSA 题目&#xff1a; from Crypto.Util.number import * from secret import flagdef padding(flag):return flagb\xff*(64-len(flag))flagpadding(flag) mbytes_to_long(flag) pgetPrime(512) qg…...

Postman轻松签名,让SHA256withRSA保驾护航!

前言 在接口测试中&#xff0c;我们经常需要对请求进行签名&#xff0c;以保证数据的安全性。而SHA256withRSA是一种较为常见的签名算法&#xff0c;它可以使用私钥对数据进行签名&#xff0c;使用公钥进行验签。 但是&#xff0c;实现该算法签名可能会涉及到一些繁琐的操作&…...

C#面:简述装箱和拆箱

在C#中&#xff0c;装箱&#xff08;boxing&#xff09;和拆箱&#xff08;unboxing&#xff09;是用于在值类型和引用类型之间进行转换的过程。 装箱&#xff1a;&#xff08;Boxing&#xff09; 是将值类型转换为引用类型的过程。 将一个值类型赋值给一个对象类型时&#x…...

【Kubernetes in Action笔记】1.快速开始

在Kubernetes上运行一个程序 基础运行环境 当前的运行环境为使用虚拟机构建的单master集群。 [rootk8s-master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane 109d v1.27.1 k8s-node1 Ready …...

踩坑实录(Fourth Day)

今天开工了&#xff0c;其实还沉浸在过年放假的喜悦中……今天在自己写 Vue3 的项目&#xff0c;虽说是跟着 B 站在敲&#xff0c;但是依旧是踩了一些个坑&#xff0c;就离谱……照着敲都能踩到坑&#xff0c;我也是醉了…… 此为第四篇&#xff08;2024 年 02 月 18 日&#x…...

【python】网络爬虫与信息提取--requests库

导学 当一个软件想获得数据&#xff0c;那么我们只有把网站当成api就可以 requests库:自动爬取HTML页面&#xff0c;自动网络请求提交 robots协议&#xff1a;网络爬虫排除标准&#xff08;网络爬虫的规则&#xff09; beautiful soup库&#xff1a;解析HTML页面 工具&…...

洛谷 P8627 [蓝桥杯 2015 省 A] 饮料换购

参考代码and代码解读 #include <bits/stdc.h> using namespace std; int main() { int n; scanf("%d", &n); int dr;//drdrink; dr n;//把drink赋值于n; while (n > 2) {//剩余的总瓶盖数要大于二,才能换得下一瓶饮料; dr n…...

Academic Inquiry|投稿状态分享(ACS,Wiley,RSC,Elsevier,MDPI,Springer Nature出版社)

作为科研人员&#xff0c;我们经常会面临着向学术期刊投稿的问题。一般来说&#xff0c;期刊的投稿状态会在官方网站上进行公示&#xff0c;我们可以通过期刊的官方网站或者投稿系统查询到我们投稿的论文的状态&#xff0c;对于不同的期刊在投稿系统中会有不同的显示。 说明&am…...

1+X运维试题样卷C卷(初级)

云计算C卷 单选题(200分) 1.在OSI模型中,HTTP协议工作在第()层,交换机工作在第()层。(10分) (答案未做:0分) A、7/3 B、7/2 (正确答案) C、6/3 D、6/2 2.Linux有三个查看文件的命令,若希望在查看文件内容过程中可以用光标上下移动来查看文件内容,应使用命令。(10分…...

Spring学习笔记(二)Spring的控制反转(设计原则)与依赖注入(设计模式)

一、控制反转&#xff1a;缩写IoC 是一种设计原则&#xff0c;降低程序代码之间的耦合度 对象由Ioc容器统一管理&#xff0c;当程序需要使用对象时直接从IoC容器中获取。这样对象的控制权就从应用程序转移到了IoC容器 二、依赖注入&#xff1a;缩写DI 依赖注入是一种消除类之…...

MySQL 基础知识(四)之表操作

目录 1 约束 2 查看已有表 3 创建表 4 查看表结构 5 修改表 6 删除表 1 约束 主键约束 primary key&#xff1a;唯一&#xff0c;标识表中的一行数据&#xff0c;此列的值不可重复&#xff0c;且不能为 NULL&#xff0c;此外&#xff0c;可以多个列组成主键唯一约束 uniq…...

计算机网络——10FTP

FTP FTP&#xff1a;文件传输协议 向远程主机上传输文件或从远程主机接收文件客户/服务器模式 客户端&#xff1a;发起传输的一方服务器&#xff1a;远程主机 ftp:RFC 959ftp服务器&#xff1a;端口号为21 FTP&#xff1a;控制连接与数据连接分开 控制连接 FTP客户端与FTP服…...

javascript中的this指向

文章目录 探索 JavaScript 中的神奇之谜&#xff1a;this关键字解析this 是什么&#xff1f;为何 this如此重要&#xff1f;this 的工作原理实例解析默认绑定隐式绑定显式绑定new 绑定 探索 JavaScript 中的神奇之谜&#xff1a;this关键字解析 JavaScript&#xff0c;作为一门…...

WebServer 之 http连接处理(下)

目录 ✊请求报文--解析 流程图 && 状态机 状态机 -- 状态转移图 主状态机 从状态机 http 报文解析 HTTP_CODE 含义 从状态机 逻辑 主状态机 逻辑 &#x1f41e;请求报文--响应 基础API stat mmap iovec writev 流程图 HTTP_CODE 含义(2) 代码分析 …...

Android电量相关知识

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、 查看耗电情况3.1 注册广播 ACTION…...

【Java多线程】线程中几个常见的属性以及状态

目录 Thread的几个常见属性 1、Id 2、Name名称 3、State状态 4、Priority优先级 5、Daemon后台线程 6、Alive存活 Thread的几个常见属性 1、Id ID 是线程的唯一标识&#xff0c;由系统自动分配&#xff0c;不同线程不会重复。 2、Name名称 用户定义的名称。该名称在各种…...