01基本介绍篇(D2_多线程问题)
目录
一、线程的上下文切换问题
1. 基本介绍
2. 多线程一定比单线程快?
3. 如何减少上下文切换
二、线程安全问题
1. 什么是线程安全?
2. java语言中的线程安全
2.1. 不可变
2.2. 绝对线程安全
2.3. 相对线程安全
2.4. 线程兼容
2.5. 线程对立
3. java实现线程安全的方法?
3.1. 互斥同步
3.2. 非阻塞同步
3.3. 无同步方案
三、资源限制问题
1. 什么是资源限制
2. 资源限制引发的问题
3. 如何解决资源限制
4. 如何在资源限制情况下,让程序更快
一、线程的上下文切换问题
1. 基本介绍
在多线程编程中,线程个数一般都大于 CPU 个数,而每个 CPU 同一时刻只能被一个线程使用,
为了让用户感觉多个线程是在同时执行的,CPU资源的分配采用了时间片轮转的策略,也就是给每
个线程分配一个时间片,线程
在时间片内占用 CPU 执行任务。当前线程使用完时间片后,就会处于就绪状态并让出CPU让其他线
程占用,这就是上下文切换,从当前线程的上下文切换到了其他线程。那么就有一个问题,让出
CPU 的线程等下次轮到自己占有
CPU时如何知道自己之前运行到哪里了?所以在切换线程上下文时需要保存当前线程的执行现场,
当再次执行时根据保存的执行现场信息恢复执行现场。
线程上下文切换时机有:当前线程的 CPU 时间片使用完处于就绪状态时,当前线程被其他线程中
断时。
简单来说:
即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机
制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执
行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。
CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个 任务。但
是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状
态。所以任务从保存到再加载的过程就是一次上下文切换。
2. 多线程一定比单线程快?
我们知道,使用多线程,可以同时执行多个任务,从表面上看,多线程明显是要快于单线程的。但
是,多线程的创建,上下文的切换也是需要开销的,所以多线程不一定比单线程快,接下来我们来
看一个简单的测试用例。
该测试用例分别使用单线程和多线程进行 a 的递增,b 的递减操作,我们通过控制循环次数,来比
较相同次数下,串行和并行所花时间。
public class TimeTest {public final int count = 1000000;public static void main(String[] args) throws InterruptedException {TimeTest timeTest = new TimeTest();System.out.println("执行 " + timeTest.count + " 次");timeTest.serial(); //串行timeTest.parallel(); //并行}public void serial() {int a = 0;int b = 0;long l = System.currentTimeMillis();for (int i = 0; i < count; i++) {a++;}for (int i = 0; i < count; i++) {b--;}System.out.println("串行----->" + (System.currentTimeMillis() - l));}public void parallel() throws InterruptedException {int b = 0;Thread thread = new Thread(new Runnable() {@Overridepublic void run() {int a = 0;for (int i = 0; i < count; i++) {a++;}}});long l = System.currentTimeMillis();thread.start();for (int i = 0; i < count; i++) {b--;}thread.join(); //等thread线程执行完毕再输出时间差System.out.println("并行----->" + (System.currentTimeMillis() - l));}
}
输出结果:
count | 100 | 10000 | 100000 | 500000 | 1000000 |
单线程(ms) | 0 | 0 | 2 | 2 | 4 |
多线程 (ms) | 0 | 0 | 2 | 3 | 2 |
由上表可以发现,执行次数在 50w 次左右,单线程比多线程快,100w 左右,多线程比单线程快,
所以,多线程不一定比单线程快。
注:以上测试结果对比可能不太明显,计算时间差时可以使用 System.nanoTime(),单位精确到纳
秒级。
得出结论:
多线程似乎一直给我们这样的印象就是多线程比单线程快,其实这是一个伪命题。
事无绝对,多线程有时候确实比单线程快,但也有很多时候没有单线程那么快。
首先简单区分一下并发性 ( concurrency ) 和并行性 ( parallel ) 。
并行是说同一时刻有多条命令在多个处理器上同时执行。
并发是说同一时刻只有一条指令执行,只不过进程(线程)指令在 CPU 中快速轮换,速度极快,给人看
起来就是”同时运行”的印象,实际上同一时刻只有一条指令进行. 但实际上如果我们在一个应用程序
中使用了多线程,线程之间的轮换以及上下文切换是需要花费很多时间的,这样的话,当我们执行类
似循环之类的操作的时候,是不是就意味着单线程一定会比多线程快呢(因为单线程的执行没有线程
切换的时间消耗)
3. 如何减少上下文切换
减少上下文切换的方法有无锁并发编程、CAS 算法、使用最少线程和使用协程。
1. 无锁并发编程
多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一 些办法来避免使用锁,
如将数据的 ID 按照 Hash 算法取模分段,不同的线程处理不同段的数据。
2. CAS算法
Java的Atomic包使用CAS算法来更新数据,而不需要加锁。
3. 使用最少线程
避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这 样会造成大量线程都处于等待状态。
4. 协程
在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。
二、线程安全问题
1. 什么是线程安全?
当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不
需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正
确的结果,那就称这个对象是线程安全的。
该定义要求线程安全的代码都必须具备一个共同特征:代码本身封装了所有必要的正确性保障手段
(如互斥同步等),令调用者无须关心多线程下的调用问题,更无须自己实现任何措施来保证多线
程环境下的正确调用。
2. java语言中的线程安全
线程安全,将以多个线程之间存在共享数据访问为前提。为了更深入地理解线程安全,我们不把线
程安全当作一个非真即假的二元排他选项来看待,而是按照线程安全的“安全程度”由强至弱来排
序,可以将java语言中各种操作共享的数据分为以下五类:
- 不可变
- 绝对线程安全
- 相对线程安全
- 线程兼容
- 线程对立
2.1. 不可变
在java语言里(JDK5之后),不可变(Immutable)的对象一定是线程安全的,无论是对象的方法
实现还是方法的调用者,都不需要再进行任何线程安全保障措施。
“final关键字带来的可见性”提到过:只要一个不可变的对象被正确的构建出来(即没有发生this引用
逃逸的情况),那其外部的可见状态永远都不会改变,永远都不会看到它在多个线程之中处于不一
致的状态。
“不可变”带来的安全性是最直接,最纯粹的。
java语言中,如果多线程共享数据分为两类:
- 基本数据类型:只要在定义时使用 final 关键字修饰它就可以保证它是不可变的。
- 对象类型:需要对象自行保证其行为不会对其状态产生任何影响。
-
- 可以类比 java.lang.String 类的对象实例,它是一个典型的不可变对象,用户调用它的 substring()、replace() 和concat()这些方法都不会影响它原来的值,只会返回一个新构造的字符串对象。
保证对象行为不影响自己状态的途径有很多种,最简单的一种就是把对象里面带有状态的变量都声
明为final,这样构造函数结束之后,它就是不可变的,如下java.lang.Integer构造函数,通过将内
部状态变量value定义为final来保障状态不变。
/*** The value of the {@code Integer}.** @serial*/private final int value;/*** Constructs a newly allocated {@code Integer} object that* represents the specified {@code int} value.** @param value the value to be represented by the* {@code Integer} object.*/public Integer(int value) {this.value = value;}
java类库API中符合不可变要求的类型:
- java.lang.String。
- 枚举类型。
- java.lang.Number的部分子类。
-
- Long和Double等数值包装类型。
- BigInteger和BigDecimal等大数据类型。
例外:同为 Number 子类型的原子类 AtomicInteger 和 AtomicLong 则是可变的。
为啥这样设计?
它们是并发包下的类,所以AtomicInteger和AtomicLong肯定是在并发环境下使用的,可以用它们
来保证并发环境下的原子性操作。
2.2. 绝对线程安全
绝对线程安全的定义是很严格的,一个类要达到“不管运行时环境如何,调用者都不需要任何额外
的同步措施”可能需要付出非常高昂的,甚至不切实际的代价。在 java API 中标注自己是线程安全
的类,大多数都不是绝对的线程安全。
我们可以通过 java API 中一个不是“绝对线程安全”的“线程安全类型”来看看这个语境里的“绝对”究
竟是什么意思。Java.util.Vector 是一个线程安全的容器,因为它的 add()、get() 和 size() 等方法都
是被 synchronized修饰的,尽管这样效率不高,但保证了具备原子性、可见性和有序性。
不过,即使它所有的方法都被修饰成 synchronized,也不意味着调用它的时候就永远都不再需要
同步手段了。
package com.zhengge.thread.security;
import java.util.Vector;public class VectorTest {private static Vector<Integer> vector = new Vector<Integer>();public static void main(String[] args) {while (true) {for (int i = 0; i < 10; i++) {vector.add(i);}Thread removeThread = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < vector.size(); i++) {vector.remove(i);}}});Thread printThread = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < vector.size(); i++) {System.out.println(vector.get(i));}}});removeThread.start();printThread.start();while (Thread.activeCount() > 20) {}}}
}
Exception in thread "Thread-1007" Exception in thread "Thread-1008" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 9at java.util.Vector.get(Vector.java:751)at com.example.xuniji.VectorTest$2.run(VectorTest.java:32)at java.lang.Thread.run(Thread.java:748)
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 7at java.util.Vector.remove(Vector.java:834)at com.example.xuniji.VectorTest$1.run(VectorTest.java:23)at java.lang.Thread.run(Thread.java:748)
尽管这里使用到的 Vector 的 get()、remove() 和 size() 方法都是同步的,但是在多线程的环境中,
如果不在方法调用端做额外的同步措施,使用这段代码仍然是不安全的。因为如果另一个线程恰好
在错误的时间里删除了一个元素,导致序号i已经不再可用,再用i访问数组就会抛出一个
ArrayIndexOutOfBoundsException 异常。
如果要保证这段代码能正确执行下去,我们不得不把 removeThread 和 printThread 定义成如下所
示:
Thread removeThread = new Thread(new Runnable() {@Overridepublic void run() {synchronized (vector) {for (int i = 0; i < vector.size(); i++) {vector.remove(i);}}}
});Thread printThread = new Thread(new Runnable() {@Overridepublic void run() {synchronized (vector) {for (int i = 0; i < vector.size(); i++) {System.out.println(vector.get(i));}}}
});
假如Vector一定要做到绝对的线程安全,那就必须在它内部维护一组一致性的快照访问才行,每次
对其中元素进行改动都要产生新的快照,这样要付出的时间和空间成本都是非常大的。
2.3. 相对线程安全
相对线程安全就是我们通常意义上所讲的线程安全,它需要保证对这个对象单次的操作是线程安全
的,我们在调用的时候不需要进行额外的保障措施,但是对于一些特定顺序的连续调用,就可能需
要在调用端使用额外的同步手段来保证调用的正确性。以上代码(Vector)就是相对线程安全的案
例。
在java语言中,大部分声称线程安全的类都属于这种类型,例如 Vector、HashTable、Collections
的synchronizedCollection()方法包装的集合等。
2.4. 线程兼容
线程兼容是指对象本身并不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象
在并发环境中可以安全地使用。
平常我们说一个类不是线程安全的,通常就是指这种情况。
Java类库API中大部分的类都是线程兼容的,比如 ArrayList 和 HashMap。
2.5. 线程对立
线程对立是指不管调用端是否采取了同步措施,都无法在多线程环境中并发使用代码。
java 语言天生就支持多线程的特性,线程对立这种排斥多线程的代码是很少出现的,通常都是有害
的,应当尽量避免。
一个线程对立的例子是 Thread 类的 suspend() 和 resume() 方法。
如果有两个线程同时持有一个线程对象,一个尝试去中断线程,一个尝试去恢复线程,在并发进行
的情况下,无论调用时是否进行了同步,目标线程都存在死锁风险。
3. java实现线程安全的方法?
3.1. 互斥同步
互斥同步是最常见、最重要的并发正确性保障手段,也称为堵塞同步。同步是指在多条线路并发访
问共享数据时,保证共享数据在同一时间只能使用一条线路(或者使用信号量时)。互斥是实现同步
的手段,临界区、互斥量和信号量是常见的互斥实现方式。因此,在互斥同步这四个字中,互斥是
原因,同步是果实的互斥是方法,同步是目的。Java中,互斥同步手段是 synchronized 关键词和
重新开锁。
3.2. 非阻塞同步
互斥同步面临的主要问题是进行线程阻塞和唤醒所带来的性能开销,互斥同步属于一种悲观的并发
策略,无论共享的数据是否会出现竞争,它都会进行加锁(这里讨论的是概念模型,实际上虚拟机
会优化掉很大一部分不必要的加锁),这将会导致用户态到核心态转换、维护锁计数器和检查是否
有被阻塞的线程需要被唤醒等开销。
随着硬件指令集的发展,锁被原子机器指令(如比较和交换指令)取代,以保证并发访问中数据的一
致性。这种乐观并发策略的实现不再需要挂起线程阻塞,所以这种同步操作称为非阻塞同步,使用
这种措施的代码通常称为无锁编程。
从 Java5.0 开始,原子变量类可以用来构建高效的非阻塞算法。
3.3. 无同步方案
要保证线程安全,也并非一定要进行阻塞或非阻塞同步,同步与线程安全两者没有必然的联系。
同步只是保障存在共享数据争用时正确性的手段,如果能让一个方法本来就不涉及共享数据,那它
自然就不需要任何同步措施去保证其正确性。
一种避免使用同步的方式就是不共享数据。这种技术被称为线程封闭 ( ThreadConfinement ),它
是实现线程安全性的最简单方式之一。
Java可以通过 java.lang.ThreadLocal 类来实现线程本地存储的功能。
三、资源限制问题
1. 什么是资源限制
资源限制是指在进行并发编程时,程序的执行速度受限于计算机硬件资源或软件资源。
例如,服务器的带宽只有 2Mb/s,某个资源的下载速度是 1Mb/s 每秒,系统启动 10 个线程下载资
源,下载速度不会变成 10Mb/s,所以在进行并发编程时,要考虑这些资源的限制。硬件资源限制
有带宽的上传/下载速度、硬盘读写速度和 CPU 的处理速度。
软件资源限制有数据库的连接数和 socket 连接数等。
2. 资源限制引发的问题
在并发编程中,将代码执行速度加快的原则是将代码中串行执行的部分变成并发执行, 但是如果
将某段串行的代码并发执行,因为受限于资源,仍然在串行执行,这时候程序不仅不 会加快执
行,反而会更慢,因为增加了上下文切换和资源调度的时间。
例如,之前看到一段程 序使用多线程在办公网并发地下载和处理数据时,导致 CPU 利用率达到
100%,几个小时都不能运行完成任务,后来修改成单线程,一个小时就执行完成了。
3. 如何解决资源限制
如何解决资源限制的问题 对于硬件资源限制,可以考虑使用集群并行执行程序。既然单机的资源
有限制,那么就让程序在多机上运行。
比如使用 ODPS、Hadoop 或者自己搭建服务器集群,不同的机器处理不同的数据。可以通过“数
据ID%机器数”,计算得到一个机器编号,然后由对应编号的机器处理这笔数据。对于软件资源限
制,可以考虑使用资源池将资源复用。
比如使用连接池将数据库和Socket连接复用,或者在调用对方webservice接口获取数据时,只建立
一个连接。
4. 如何在资源限制情况下,让程序更快
在资源限制情况下进行并发编程如何在资源限制的情况下,让程序执行得更快呢?
方法就是,根据不同的资源限制调整程序的并发度。
- 比如下载文件程序依赖于两个资源——带宽和硬盘读写速度。
- 有数据库操作时,涉及数据库连接数,如果 SQL 语句执行非常快,而线程的数量比数据库连接数大很多,则某些线程会被阻塞,等待数据库连接。
相关文章:
01基本介绍篇(D2_多线程问题)
目录 一、线程的上下文切换问题 1. 基本介绍 2. 多线程一定比单线程快? 3. 如何减少上下文切换 二、线程安全问题 1. 什么是线程安全? 2. java语言中的线程安全 2.1. 不可变 2.2. 绝对线程安全 2.3. 相对线程安全 2.4. 线程兼容 2.5. 线程对立…...
如何保证光谱相机的稳定性和可靠性
光学系统设计与制造 高质量光学元件:采用高精度研磨和镀膜的透镜、棱镜、光栅等光学元件。优质的透镜可以减少像差和色差,确保光线准确聚焦;高质量的镀膜能够提高光学元件的透光率,降低反射损失,并且增强对不同波段光…...
基于springboot+vue的洪涝灾害应急信息管理系统设计与实现
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
登录、注册、忘记密码、首页HTML模板
<!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>登录</title><style>body {display: fl…...
HTML文章翻页功能
效果展示: 效果原理: 1、引入CDN 2、绘制文章翻页样式,以及自动分段 3、获取窗口宽高,计算出当前文章总分段,并实现分页 4、完整代码 <!DOCTYPE html> <html><head><meta charset"utf-8&qu…...
JAVA安全编码规范
1. 数据校验 对外部输入进行校验入参的合法性, 防止内存越界,命令注入,SQL注入,格式化字符串漏洞 校验长度,范围,输入校验采用白名单形式 校验前做归一化处理,使用java.text.Normalizer的n…...
OpenGL —— 基于Qt的视频播放器 - ffmpeg硬解码,QOpenGL渲染yuv420p或nv12视频(附源码)
运行效果 工程说明 源码 vertex.glsl...
爬虫逆向学习(十五):Akamai 3.0反爬分析与sensor-data算法逆向经验
此分享只用于学习用途,不作商业用途,若有冒犯,请联系处理 Akamai 3.0反爬分析与sensor-data算法逆向经验 Akamai开始正题前须知站点信息接口分析反爬点反爬点定位_abck定位结果 逆向前准备工作sensor_data生成位置本地替换文件 请求体sensor…...
java项目启动时,执行某方法
1. J2EE项目 在Servlet类中重写init()方法,这个方法会在Servlet实例化时调用,即项目启动时调用。 import javax.servlet.ServletException; import javax.servlet.http.HttpServlet;public class MyServlet extends HttpServlet {Overridepublic void …...
学会使用开源软件jclasslib 字节码文件的组成 详解
应用场景 1 应用场景 2 学习路线 以正确的姿势打开文件 字节码文件的组成 玩转字节码常用工具 以正确的姿势打开文件 开源软件 jclasslib github 地址 https://github.com/ingokegel/jclasslib 工具使用 字节码文件的组成 基本信息 常量池 字段 方法 属性 详解 魔数 主副版…...
Flask表单处理与验证
Flask是一个轻量级的Python框架,它通过扩展库提供了对表单处理与验证的支持。WTForms是一个流行的Flask扩展库,用于创建和验证Web表单。它提供了一种声明式的方法来定义表单结构和验证逻辑,使得表单处理更为简洁和优雅。下面,我们…...
如何通俗易懂的理解 html js css
HTML、CSS 和 JavaScript 是构建网页的三大核心技术。为了通俗易懂地理解它们,我们可以用一个简单的比喻:**盖房子**。 --- ### 1. **HTML:房子的结构** HTML(HyperText Markup Language)就像房子的**骨架**。它定义…...
信凯科技业绩波动明显:毛利率远弱行业,资产负债率偏高
《港湾商业观察》施子夫 1月8日,深交所官网显示,浙江信凯科技集团股份有限公司(以下简称“信凯科技”)主板IPO提交注册。 自2022年递交上市申请,信凯科技的IPO之路已走过两年光景,尽管提交注册࿰…...
蓝牙BT04-A的使用与相关AT指令
一、AT指令没有返回的问题及解决方案 检查指令格式: 确认指令格式是否正确,包括特定的命令和结尾的回车换行符(n)。 检查TX/RX连接: 确认TX(发送)和RX(接收)线是否连接正…...
新手如何练习SQL?|掌握
对于新手想要练习SQL语句,可以从以下几个方面入手: 1. 建立理论基础 首先深入理解数据库的核心组件,包括数据库本身、其内部的各个表、表中的字段及其对应的数据类型(如字符串、整型、日期等),以及数据库…...
JavaScript宝典下
小哆啦闭关修炼已久,潜心攻读专业秘技,方才下山考研本欲大展宏图,怎奈山河虽壮志难酬,终是觉察考研无望。思来想去,不若弃考研之念,重拾敲代码之道,复盘前端奇术,以备闯荡职场江湖。…...
浅谈云计算12 | KVM虚拟化技术
KVM虚拟化技术 一、KVM虚拟化技术基础1.1 KVM虚拟化技术简介1.2 KVM虚拟化技术架构1.2.1 KVM内核模块1.2.2 用户空间工具(QEMU、Libvirt等) 二、KVM虚拟化技术原理2.1 硬件辅助虚拟化2.2 VMCS结构与工作机制 三、KVM虚拟化技术面临的挑战与应对策略3.1 性…...
Spring Boot 动态表操作服务实现
Spring Boot 动态表操作服务实现 Spring Boot 动态表操作服务实现1. 环境配置2. JdbcTemplate 的使用2.1 创建动态表2.2 动态添加字段2.3 动态删除字段2.4 动态修改字段类型2.5 删除表的方法实现 3. 小结3.1 可能的优化 Spring Boot 动态表操作服务实现 在现代的应用开发中&am…...
62_Redis服务器集群优化
Redis集群虽然具备高可用特性,且能实现自动故障恢复,但是如果使用不当,也会存在一些问题,总结如下。 集群完整性问题集群带宽问题数据倾斜问题客户端性能问题命令的集群兼容性问题Lua和事务问题1.集群完整性问题 在 Redis 集群的默认配置下,当节点检测到存在至少一个哈希…...
晨辉面试抽签和评分管理系统之九:随机编排考生的分组(以教师资格考试面试为例)
晨辉面试抽签和评分管理系统(下载地址:www.chenhuisoft.cn)是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…...
Linux Top 命令 load average 指标解读
前言 作为平台开发的同学,维护平台稳定性是我们最基本的工作职责,下面主要介绍下top 命令里 ,load average 这个指标如何去衡量机器负载程度。 概念介绍 load average 是系统在过去 1 分钟、5 分钟、15 分钟 的平均负载,它表示运…...
Nacos: 一个动态服务发现与配置管理平台
Nacos: 一个动态服务发现与配置管理平台 引言 在微服务架构日益普及的今天,服务之间的调用和配置管理变得越来越复杂。为了简化这一过程并提高开发效率,阿里巴巴推出了Nacos——一个易于使用的动态服务发现、配置管理和服务管理平台。 Nacos是什么&am…...
SpringBoot + 事务钩子函数
一、案例背景 拿支付系统相关的业务来举例。在支付系统中,我们需要记录每个账户的资金流水(记录用户A因为哪个操作扣了钱,因为哪个操作加了钱),这样我们才能对每个账户的账做到心中有数,对于支付系统而言&…...
OpenCV相机标定与3D重建(56)估计物体姿态(即旋转和平移)的函数solvePnPRansac()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 使用RANSAC方案从3D-2D点对应关系中找到物体的姿态。 cv::solvePnPRansac 是 OpenCV 中用于估计物体姿态(即旋转和平移)的…...
【JVM中的三色标记法是什么?】
JVM中的三色标记法是什么? 一、基本概念二、标记过程三、优势与问题四、漏标与多标的解决方案三色标记法(Tri-color Marking Algorithm)是Java虚拟机(JVM)中一种用于追踪对象存活状态的垃圾回收算法。 它基于William D. Hana和Mark S. McCulleghan在1976年提出的两色标记法…...
从0开始学习搭网站第二天
前言:今天比较惭愧,中午打铲吃了一把,看着也到钻二了,干脆顺手把这个赛季的大师上了,于是乎一直到网上才开始工作,同样,今天的学习内容大多来自mdn社区mdn 目录 怎么把文件上传到web服务器采用S…...
43.Textbox的数据绑定 C#例子 WPF例子
固定最简步骤,包括 XAML: 题头里引入命名空间 标题下面引入类 box和block绑定属性 C#: 通知的类,及对应固定的任务 引入字段 引入属性 属性双触发,其中一个更新block的属性 block>指向box的属性 从Textbo…...
钉钉实现第三方登录示例(重复回调问题解析)
钉钉作为专门为企业打造的沟通协助平台,包含的功能很多,考勤打卡,审批,日记,钉盘,钉邮等。基本满足了一些中小企业的大部分工作需求。因此对接钉钉的一些功能模块业务需求在开发中也是比较常见的。钉钉的开…...
Vue2+OpenLayers添加/删除点、点击事件功能实现(提供Gitee源码)
目录 一、案例截图 二、安装OpenLayers库 三、安装Element-UI 四、代码实现 4.1、添加一个点 4.2、删除所有点 4.3、根据经纬度删除点 4.4、给点添加点击事件 4.5、完整代码 五、Gitee源码 一、案例截图 可以新增/删除标记点,点击标记点可以获取到当前标…...
算法妙妙屋-------2..回溯的奇妙律动
回溯算法是一种用于系统性地搜索和解决问题的算法,它以深度优先搜索(DFS)为基础,用来探索所有可能的解决方案。通过递归地尝试候选解并在必要时回退(即“回溯”),它能够高效地解决许多涉及组合、…...
pytest-instafail:让测试失败信息即时反馈
pytest-instafail:让测试失败信息即时反馈 前言一、简介二、优势三、安装与使用3.1 未安装时运行情况3.2 安装3.3 已安装时运行情况3.3 pytest.ini 配置选项 四、对比 总结 前言 当测试用例数量庞大时,定位测试失败的原因往往耗时费力。此时,…...
K8S--配置存活、就绪和启动探针
目录 1 本人基础环境2 目的3 存活、就绪和启动探针介绍3.1 存活探针3.2 就绪探针3.3 启动探针 4 探针使用场景4.1 存活探针4.2 就绪探针4.3 启动探针 5 配置存活、就绪和启动探针5.1 定义存活探针5.2 定义一个存活态 HTTP 请求接口5.3 定义 TCP 的就绪探针、存活探测5.4 定义 g…...
solidity基础 -- 枚举
在智能合约开发领域,Solidity语言因其简洁高效而被广泛使用。其中,枚举(enum)作为一种特殊的数据类型,为合约的状态管理提供了极大的便利。本文将通过一个具体的Solidity合约示例,深入探讨枚举的定义、使用…...
重回C语言之老兵重装上阵(六)枚举
1. 什么是枚举 (enum)? 枚举(enum)是 C 语言中的一种数据类型,用于定义一组具名的整数常量。它可以使代码更加可读,帮助程序员更容易理解程序中的常量值。通过枚举,程序员可以使用有意义的名称来代替数字&…...
python+playwright自动化测试(一):安装及简单使用,截图录屏
目录 基本使用 浏览器调用 启用浏览器 创建窗口对象 访问URL 页面的刷新、返回、前进 关闭 截图、录屏、保存pdf 截图 录屏 保存为pdf 设置窗口大小 调试模式 手机模式及new_context的更多参数 手机模式 new_context的其他参数 设置语言和时区 设置和修改位置…...
Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)
MySQL是一种广泛使用的关系型数据库管理系统(RDBMS),其体系结构设计旨在提供高效的数据存储、查询处理和事务管理。MySQL的体系结构可以分为多个层次,每个层次负责不同的功能模块。 MySQL的体系结构主要由以下几个部分组成&#…...
git merge 压缩提交
在 Git 中,执行 git merge 时可以通过一些操作来“压缩”提交,通常是指将合并过程中的多个提交压缩成一个单一的提交。这可以通过使用 --squash 选项来完成,或者在合并后进行交互式 rebase。以下是两种常见的方法: 方法 1&#x…...
Python脚本自动发送电子邮件
要编写一个Python脚本来自动发送电子邮件,你可以使用smtplib库来处理SMTP协议,以及email库来构建邮件内容。 安装必要的库 通常情况下,smtplib和email库是Python标准库的一部分,因此不需要额外安装。如果你使用的是较旧的Python版…...
uniapp中rpx和upx的区别
在 UniApp 中,rpx 和 upx 是两种不同的单位,它们的主要区别在于适用的场景和计算方式。 ### rpx(Responsive Pixel) - **适用场景**:rpx 是一种响应式单位,主要用于小程序和移动端的布局。 - **计算方式**…...
CentOS 9 Stream 中查看 Python 版本并升级 Python
CentOS 9 Stream 中查看 Python 版本并升级 Python 1. 查看当前 Python 版本2. 升级 Python 版本(1)安装开发工具(2)安装必要的依赖包(3)下载和安装新版本的 Python(4)验证安装 3. …...
可以用于分割字符串的方法(python)
一、str.split(sep,maxsplit)函数(返回列表) sep:分隔符 maxsplit:分割次数 a"Hello world" list1a.split(" ",1) print(list1) 结果: [Hello, world] 二、str.rsplit(sep,maxsplit)函数&…...
【Vue】全局/局部组件使用流程(Vue2为例)
全局组件和局部组件区别 如何使用 全局组件:全局注册后,可以在任意页面中直接使用。局部组件:在页面中需要先导入子组件路径,注册组件才能使用。 适用场景 全局组件:适用于高频使用的组件,如导航栏、业…...
virtual box虚拟机误删Python3.6后导致UBUNTU18.04开机无UI界面(进不了desktop)的解决方法
最近在解决一个python引起的问题的时候,作者心一狠,删了系统自带的python3.6, 顺便还删了python3。导致重启后ubuntu的virtual box虚拟机无法看到UI登录界面,只给我了孤零零的命令行。装了很多东西不可能重装,无奈只能…...
虚拟线程JDK与Spring Core Reactor
两种虚拟线程对比:JDK vs. Spring Core Reactor性能对比 1、基于 JDK 的虚拟线程实现: 摘自实际代码: public static void withFlatMapUsingJDK() { ... var virtualThreadExecutor Executors.newThreadPerTaskExecutor( Thread .ofVirtual…...
纯 Python、Django、FastAPI、Flask、Pyramid、Jupyter、dbt 解析和差异分析
一、纯 Python 1.1 基础概念 Python 是一种高级、通用、解释型的编程语言,以其简洁易读的语法和丰富的标准库而闻名。“纯 Python” 在这里指的是不依赖特定的 Web 框架或数据分析工具,仅使用 Python 原生的功能和标准库来开发应用程序或执行任务。 1.…...
C++ NULL和nullptr
NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码: #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif 如上是条件编译的宏定义 确保在不同编程环境下正确处理NULL的定义 C中NULL可能被定义…...
算法日记1:洛谷p2678跳石头(二分答案)
1、题目 二、题解: 2.1解题思路: 1.题目要求求出最小值最大,明显的二分答案题目,所以我们可以二分可以跳跃距离int l-1,rL1; 2.此时我们思考lmid和rmid的处理,当我们的check(mid)为true时候 表明我们此时的mid是符合要求的, 那么…...
PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析
PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析 目录 PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析1. 引言2. PID控制器的基本概念2.1 PID控制器的定义2.2 PID控制器的核心思想2.3 PID控制器的应用领域 3. PID控…...
Vue中nextTick实现原理
源码实现思路(面试高分回答) 面试官问我 Vue 的 nextTick 原理是怎么实现的,我这样回答: 在调用 this.$nextTick(cb) 之前: 存在一个 callbacks 数组,用于存放所有的 cb 回调函数。存在一个 flushCallbac…...
【MATLAB】subplot如何增加title
在 Matlab 中,使用 subplot 函数将图形窗口划分为多个子图,并使用 title 函数为每个子图添加标题。以下是一个示例: matlab % 生成示例数据 x 0:0.1:10; y1 sin(x); y2 cos(x); % 创建一个 2 行 1 列的子图布局,并选…...