网站底部设计代码/seo怎么读
目录
一、线程内存模型
1. 内存模型
2. 内存模型操作
二、Happens-Before原则
三、Java线程
1. 线程实现方式
2. Java线程状态
四、Java线程安全
1. 线程安全程度
2. 锁优化
五、参考资料
一、线程内存模型
1. 内存模型
内存模型主要目的是定义共享变量的访问规则,共享变量如:实例字段、静态字段、数组元素等线程共享变量(不包含线程私有变量)。内存模型中有:主内存、工作内存,如下图所示是两者交互关系,看出主内存直接对应于物理硬件的内存,而程序运行时主要访问的是工作内存。
- 主内存(Main Memory):内存模型规定所有变量都存储在主内存中;
- 工作内存(Working Memory):每个线程都有自己的内存,且变量是主内存的副本。
线程对变量的操作只能在工作内存,无法直接读写主内存;线程之间变量传递必须通过主内存实现,模型如下图所示。
注意:内存模型与内存区域划分没有任何关系,若勉强有关系,则:主内存对应堆对象实例,工作内存对应JVM栈的部分区域。
2. 内存模型操作
内存模型操作,即:主内存与工作内存交互,定义了8种原子性操作:lock、unlock、read、load、use、assign、store、write,如下表所示。
内存模型操作 | 特点 |
lock (锁定) | 范围:主内存变量; 作用:把变量标识为一个线程独占的状态。 |
unlock (解锁) | 范围:主内存变量; 作用:释放处于锁定状态的变量,后才能被其他线程锁定。 |
read (读取) | 范围:主内存变量; 作用:把变量的值从主内存传输到线程工作内存中,以便后续load操作。 |
load (载入) | 范围:工作内存变量; 作用:把read操作获取的变量值存储到工作内存的变量副本中。 |
use (使用) | 范围:工作内存变量; 作用:把变量的值传递给执行引擎(每遇到使用该变量的字节码指令)。 |
assign (赋值) | 范围:工作内存变量; 作用:把执行引擎接收到的值赋给工作内存的变量 (每遇到给变量赋值的字节码指令)。 |
store (存储) | 范围:工作内存变量; 作用:把变量的值从工作内存传输到主内存中,以便后续write操作。 |
write (写入) | 范围:主内存变量; 作用:把store操作获取的变量值存储到主内存中。 |
注意: a.一个变量从主内存复制到工作内存:必须顺序执行read、load操作,但可以不连续执行; 一个变量从工作内存同步到主内存:必须顺序执行store、write操作,但可以不连续执行; b.8种操作满足以下规则: 1):read和load、store和write不允许单独出现,即:不会出现回写主内存但其不接受; 2):不允许线程丢弃最近的assign,即:工作内存值改变,则必须同步到主内存; 3):不允许线程不原因的同步到主内存,即:不允许没有assign操作就同步到主内存; 4):一个新变量主内存诞生,即:对变量进行use、store时,则必须先执行assign、load; 5):同一时刻只有一个线程对变量lock(同一线程多次lock,则必须多次unlock后才释放); 6):执行lock时,则必须清空工作内存中此变量的副本值,后使用时重新执行load、assign; 7):执行unlock之前,则必须把此变量同步到主内存中; c.Java内存模型操作简化为:read、write、lock、unlock的四种操作。 |
从上表看出,内存模型主要围绕并发过程中如何处理原子性、可见性、有序性建立的,这三大特性如下图所示。
注意:只有一条字节码指令也不意味着是原子性,解释器要运行多行代码才能实现其语义;volatile修饰的变量具有特性:可见性、禁止指令重排序;"long和double的非原子协定":没有volatile修饰的64位数据的读写操作划分为两次32位操作,但一般认为是原子操作(概率极低)。
二、Happens-Before原则
Happens-Before原则(先行发生原则)定义两操作之间的偏序关系,因此并发安全问题不要受时间顺序影响,一切按先行发生原则为准。无需任何同步手段保证先行发生规则,如下表所示。
先行发生原则 | 特点 |
程序次序规则 | 同一个线程内,按照控制流顺序,在前的操作先行发生于其后的操作 |
管程锁定规则 | 释放锁操作先行发生于同一个锁的加锁操作 |
volatile变量规则 | volatile变量写操作先行发生于读操作 |
线程启动规则 | Thread线程start()方法先行发生于此线程的每一个动作 |
线程终止规则 | 线程中所有操作先行发生于对此线程的终止检查 |
线程中断规则 | 线程interrupt()方法调用先行发生于被中断代码检查到中断时间的发生 |
对象终结规则 | 对象构造函数完成先行发生于它的finalize()方法的开始 |
传递性 | 操作A先行发生于操作B,操作B先行发生于操作C,则A先行发生于C |
三、Java线程
1. 线程实现方式
线程是轻量级进程,各个线程共享进程资源(内存地址、I/O等)、又可以独立调度,把一个进程的资源分配和执行调用分开。实现线程有3种方式:内核线程实现(1:1)、用户线程实现(N:1)、混合实现(M:N),如下表所示。
线程实现 | 特点 |
内核线程实现 (1:1) | 1.“内核线程”:直接由OS内核完成,内核完成线程切换,操纵调度器对线程调度,并负责将线程的任务映射到各个CPU上(每个内核线程可以视为内核的一个分身); 2.每个轻量级进程(线程)都有一个内核线程支持,即:1:1实现; 3.缺点: a.系统调用代价大,需要在用户态与内核态来回切换; b.OS支持轻量级进程的数量有限; 4.Java线程采用内核线程实现。 |
用户线程实现 (N:1) | 1.“用户线程”:线程非内核线程,线程的创建、同步、销毁及调度在用户态中完成无需内核的帮助,映射到一个CPU上,即:N:1实现; 2.优点:无需切换到内核,因此速度快、低耗;更大规模的线程数; 缺点:线程调度实现复杂;增大线程被阻塞的风险。 |
混合实现 (M:N) | 内核和用户线程混合使用,用户负责线程的创建、同步、销毁;内核线程负责线程调度。 |
Java线程实现方式采用内核线程实现,每一个java线程都直接映射到一个内核线程上,HotSpot不会干涉线程的调度。
线程调度(Scheduler)是指线程分配处理器使用权的过程,两种调度方式:协同式(协程)、抢占式(java采用),如下表所示。
实现方式 | 特点 |
协同式线程调度 - 协程 (Cooperative Threads-Scheduling) | 1.线程执行时间由线程本身控制,线程工作执行完后,主动通知系统切换到另外的线程上; 2.优点:切换操作对线程可知;实现简单; 缺点:线程执行时间不可控,若代码有问题,则一直阻塞; 3.应用:Lua语言的“协同例程”。 |
抢占式线程调度 - Java采用 (Preemptive Threads-Scheduling) | 1.线程执行时间由系统来分配执行时间,如:Thread::yeild()方法可以主动让出时间,但无法主动获取执行时间; 2.通过线程优先级可以“建议”OS多分配执行时间,但是不能稳定,最终还是OS决定。 |
Java线程调度方式采用抢占式线程调度,因此Java中不能通过线程优先级完全准确判定一组Ready状态的线程会先执行哪一个。而Thread类大部分API都是Native修饰,而Native往往是该方法没有使用或无法使用平台无关的手段来实现。
2. Java线程状态
Java线程状态有6种状态:新建、运行(Runnable = Running + Ready)、无限期等待、限期等待、阻塞、结束,如下表所示。
线程状态 | 特点 |
新建 (New) | 创建后但尚未启动,即:new之后,start()之前 |
运行 (Running + Ready) | 包含两种状态:正在运行Running、正在等待系统分配执行时间Ready |
无限期等待 (Waiting) | 1.处于:线程不会被分配处理器执行时间,需被其他线程显示唤醒; 2.方法有: 没有设置timeout参数的Object::wait(),若加锁会释放锁; 没有设置timeout参数的Object::join(); LockSupport::park()。 |
限期等待 (Timed Waiting) | 1.处于:线程不会被分配处理器执行时间,无需被其他线程显示唤醒,在一定时间之后系统会自动唤醒; 2.方法有: Thread::sleep(),若加锁不会释放锁; 设置timeout参数的Object::wait(),若加锁会释放锁; 设置timeout参数的Object::join(); LockSupport::parkNanos()、LockSupport::parkUntil()。 |
阻塞 (Blocked) | 1.处于:线程被阻塞,需等待获取排他锁; 2.“阻塞状态”与“等待状态”的区别: 阻塞状态:需等待获取排他锁,建立在另一线程释放锁之上; 等待状态:等待一段时间或唤醒动作的发生。 |
结束 (Terminated) | 已终止线程的状态 |
任意时间点,线程有且只有其中一种状态,6种状态之间切换关系如下图所示。
四、Java线程安全
1. 线程安全程度
多线程访问同一对象,不用考虑线程运行环境时的调度和交替执行,也不使用同步手段或调用方不进行协调操作时,使用该对象都能获取正确的结果,则称该对象是线程安全的。根据安全层度分为5种(依次降低):不可变、绝对线程安全、相对线程安全、线程兼容、线程对立,如下表所示。
线程安全程度 | 特点 |
不可变 | 1.不可变的共享对象,一定是线程安全的,无论是对象的方法还是调用者; 2.共享数据是基本数据类型,用final修饰来保证不可变; 共享数据是对象数据类型,需要对象自行保证自己的行为对其不受任何影响,如:String对象的substring()、replace()、concat()不会影响原值,只返回一个新构造的字符串对象; 3.不可变对象有:final修饰的基本类型、String、AtomicInteger、AtomicLong。 |
绝对线程安全 | 1.“绝对安全”:不管运行如何,调用者都无需任何额外的同步手段; 2.Java中绝大多数都不是绝对安全,而是相对安全。 |
相对线程安全 | 1.“相对安全”:对象单次操作是线程安全的,调用时无需额外的同步手段; 2.若是连续调用,则需要调用端额外的同步手段; 3.相对线程安全类:Vector、HashTable等。 |
线程兼容 | 1.“线程兼容”:对象本身不是线程安全,需要调用端额外的同步手段; 2.线程兼容的类:ArrayList、HashMap等。 |
线程对立 | 1.“线程对立”:无论是否同步,都无法在多线程环境并发使用; 2.Java天生支持多线程特性,应避免尽可能避免线程对立,会出现死锁。 |
注意:线程安全是以多线程之间存在共享数据为前提;不可变对象,如:String对象的substring()、replace()、concat()不影响原值,只返回一个新构造的字符串对象。
现实线程安全有3种方式:互斥同步(阻塞同步)、非阻塞同步、无同步,如下表所示。
线程安全现实 | 特点 |
互斥同步 (阻塞同步) | 1.“同步”:多线程并发访问时,保证共享数据同一时刻只能被一个线程使用; 2.互斥是实现同步的手段,如:互斥量、信号量、临界区等手段; 3.sychronized(重量级)实现互斥(monitorenter、monitorexit两指令完成): a.当前线程持有锁后,锁计数器+1;而monitorexit则锁计数器减一,直到计数器为0时,才释放锁; b.可重入,即:同一线程反复进入同步块不会出现自锁现象; c.当前持有锁线程没有释放锁之前,其他线程无条件的被阻塞; 4.Lock接口(轻量级): a.必须在finally块中手动释放锁; b.获取锁时,可以超时中断; c.可以实现公平锁、非公平锁; d.锁绑定多个条件; 5.互斥同步属于悲观的并发策略; 6.缺点:线程阻塞和唤醒带来的性能开销。 |
非阻塞同步 | 1.基于冲突检查的乐观并发策略,共享数据检查到冲突,进行补偿措施(如重试)达到一致,不需要其他线程挂起; 2.常用处理器指令集:比较并交换(CAS_常用)、交换Swap等; 3.CAS:x86指令集使用cmpxchg完成CAS;“ABA问题”,解决:时间戳控制版本。 |
无同步 | 1.线程安全的代码无需同步,如:可重入代码、ThreadLocal; 2.“可重入代码”:代码执行的任何时候中断,去执行另一段代码,而控制权返回时原程序不会出现任何错误和对结果的影响; 3.所有可重入代码是线程安全的;但是线性安全的代码不一定是可重入代码。 |
注意:sychronized可重入,即:同一线程反复进入同步块不会出现自锁现象,当前持有锁线程没有释放锁之前,其他线程无条件的被阻塞;JDK5后类库使用CAS操作(Unsafe类完成)但是用户无法使用CAS;JDK9后VarHandle类开放面向程序使用CAS。
2. 锁优化
JDK6各种锁优化技术:自旋锁、自适应自旋锁、锁消除、锁粗化、轻量级锁、偏向锁,如下表所示。
锁优化 | 特点 |
自旋锁 | 1.“自旋锁”:等待获取锁的阻塞线程,执行忙循环(自旋),而不是切换线程; 2.自旋等待避免线程切换的开销,但是占用CPU处理时间,因此:自旋超出限定次数仍没有成功,则线程挂起; 3.开启自旋-XX:+UseSpining(JDK6默认开启);自旋次数-XX:PreBlockSpin(10次)。 |
自适应自旋锁 | 1.“自适应”:自旋次数不固定,由前一次在同一锁对象的自旋时间及锁状态决定; 2.自旋等待成功获取锁,且持有锁线程正在运行,那么自旋可以多等待相对更长时间;若是自旋很少能成功获得锁,则以后获取这个锁时可能直接省掉自旋过程。 |
锁消除 | 1.“锁消除”:即时编译在运行时,一些同步代码被检测到不存在共享数据竞争的锁,则进行锁消除; 2.锁消除判定依据是逃逸分析数据支持(堆数据不会被其他线程访问)。 |
锁粗化 | 1.“锁粗化”:连续操作都对同一对象加锁,则把加锁同步的范围扩展(粗化)到整个操作的外部; 2.适用:连续StringBuffer::append()、循环体中加锁。 |
轻量级锁 | 1.“轻量级锁”:两线程竞争同一把锁;两条以上线程竞争同一把锁,则轻量级锁(非阻塞同步 _ CAS)膨胀为重量级锁(互斥同步); 2.轻量级加锁工作过程: step1:程序进入同步代码块时,判定对象是否被锁定(锁标志位01状态); step2:没有被锁定,则在当前栈帧中创建锁记录(Lock Record)空间,用于存储锁对象目前的“Mark Word”的拷贝; step3:CAS操作把对象的“Mark Word”更新为锁记录(Lock Record)空间地址; step4:更新成功则当前线程加锁成功,且锁标志位改为00状态; 更新失败(说明至少存在另一线程产生相互竞争),首先检查“Mark Word”是否指向当前线程的栈帧,若是则说明当前已经持有锁,直接进入代码块;否则被其他线程线程已加锁。 step5:存在两条以上线程竞争加锁,则轻量级锁膨胀为重量级锁(锁标志位10状态),后续线程进入阻塞状态。 |
偏向锁 | 1.“偏向锁”:锁无竞争的情况下把整个同步消除掉,即:持有偏向锁的线程无需同步操作。 2.进入偏向锁模式:锁标志位01状态 + 偏向模式设置为1;一旦有其他线程尝试获取锁,则:偏向模式结束、锁定对象是否处于锁定状态决定是否撤销偏向锁(偏向模式设置为0)、标志位转为01(未锁定)或00(轻量级锁)状态; 3.JDK6启用偏向锁-XX:+UseBiasedLocking。 |
偏向锁、轻量级锁的状态转换及对象Mark Word的关系,如下图所示。
五、参考资料
Java线程<一> _ 介绍_爱我所爱0505的博客-CSDN博客
volatile与synchronized实现原理_synchronized底层是总线锁吗_爱我所爱0505的博客-CSDN博客
Java内存模型<一> _ 基础_爱我所爱0505的博客-CSDN博客
Java内存模型<二> _ volatile/synchronized/final内存语义_volitale final sync_爱我所爱0505的博客-CSDN博客
Java线程<三> _ 线程间通信_java 三个线程间通信_爱我所爱0505的博客-CSDN博客
Lock锁<一> _ 基础_在lock锁的队列中,什么时候前一个节点会唤醒后一个节点_爱我所爱0505的博客-CSDN博客
Lock锁<二> _ 重入锁/读写锁_读写锁可重入锁_爱我所爱0505的博客-CSDN博客
深入理解Java内存模型(一)——基础_Java_程晓明_InfoQ精选文章
相关文章:

HotSpot虚拟机之内存模型与线程安全
目录 一、线程内存模型 1. 内存模型 2. 内存模型操作 二、Happens-Before原则 三、Java线程 1. 线程实现方式 2. Java线程状态 四、Java线程安全 1. 线程安全程度 2. 锁优化 五、参考资料 一、线程内存模型 1. 内存模型 内存模型主要目的是定义共享变量的访问规则&…...

TiDB 多集群告警监控-中章-融合多集群 Grafana
作者: longzhuquan 原文来源: https://tidb.net/blog/ac730b0f 背景 随着公司XC改造步伐的前进,越来越多的业务选择 TiDB,由于各个业务之间需要物理隔离,避免不了的 TiDB 集群数量越来越多。虽然每套 TiDB 集群均有…...

【图像分类】基于卷积神经网络和主动学习的高光谱图像分类(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

notepad++ verilog关键字自动补全
新建verilog.xml放在安装目录下 D:\Program Files (x86)\Notepad\autoCompletion <?xml version"1.0" encoding"Windows-1252" ?> <NotepadPlus><AutoComplete><KeyWord name"accept_on" /><KeyWord name"a…...

C语言知识
C语言知识 链接 C语言中的数组初始化是有三种形式的,分别是: (1)数据类型 数组名称[长度n] {元素1,元素2…元素n}; (2)数据类型 数组名称[] {元素1,元素2…元素n}; (3)数据类型 数组名称[长度n]; 数组名称[0] 元素1; 数组名称[1] 元素2; 数组…...
数据结构基础
将节点构建成树 数据的结构逻辑结构集合线性结构树形结构图状结构 存储结构合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如…...

深度学习中数据处理相关的技巧
文章目录 提取隐蔽特征惰性加载数据集类别分布不均衡 提取隐蔽特征 在某些任务中,一些类别的特征可能相对较为罕见或难以捕捉。由于这些特征在数据集中出现的频率较低,模型可能无法充分学习它们,从而导致对这些类别的辨别能力较弱。为了解决…...

wkhtmltopdf 与 .Net Core
wkhtmltopdf 是使用webkit引擎转化为pdf的开源小插件. 其有.NET CORE版本的组件,DinkToPdf,但该控件对跨平台支持有限 。 是由于各系统平台会产生不同的编译结果,故windows上使用.dll,而Linux上的动态链接库是.so 所以你需要在Linux系统上安装相关wkhtmltox软件。 我这里准备了…...

Linux Mint 21.3 计划于 2023 年圣诞节发布
Linux Mint 项目近日公布了基于 Ubuntu 的 Linux Mint 发行版下一个重要版本的一些初步细节,以及备受期待的基于 Debian 的 LMDE 6(Linux Mint Debian Edition)版本。 近日,Linux Mint 项目负责人克莱门特-勒菲弗(Clem…...

腾讯云3年轻量应用服务器2核4G5M和2核2G4M详细介绍
腾讯云轻量应用服务器3年配置,目前可以选择三年的轻量配置为2核2G4M和2核4G5M,2核2G4M和2核4G5M带宽,当然也可以选择选一年,第二年xufei会比较gui,腾讯云百科分享腾讯云轻量应用服务器3年配置表: 目录 腾…...

rabbitmq中的消息确认
如何保证消息被全部消费 应用场景:我们不想丢失任何任务消息。如果一个工作者(worker)挂掉了,我们希望任务会重新发送给其他的工作者(worker)。 为了防止消息丢失,RabbitMQ提供了消息响应&…...

jenkins一键部署github项目
个人目前理解jenkins部署分为两步: 构建项目,如生成jar自动执行sh脚本 如果没有jenkins,我们可能需要将jar移动到服务器,然后执行java -jar跑程序,jenkins可以替代我们执行这些东西,下面从0开始࿰…...

岩土工程安全监测隧道中使用振弦采集仪注意要点?
岩土工程安全监测隧道中使用振弦采集仪注意要点? 岩土工程的安全监测是非常重要的,它可以帮助工程师及时发现可能存在的问题,并及时解决,保障施工进度以及施工质量,保障工程的安全运行。其中,振弦采集仪是…...

第四章nginx组件精讲
nginx配件location匹配的规则和优先级(重点面试题) RUI:统一资源标识符,是一种字符串标识,用于标识抽象的或者物理资源(文件,图片,视频) nginx当中:uri ww…...

LlamaGPT -基于Llama 2的自托管类chatgpt聊天机器人
LlamaGPT一个自托管、离线、类似 ChatGPT 的聊天机器人,由 Llama 2 提供支持。100% 私密,不会有任何数据离开你的设备。 推荐:用 NSDT编辑器 快速搭建可编程3D场景 1、如何安装LlamaGPT LlamaGPT可以安装在任何x86或arm64系统上。 首先确保…...

常见的跨域解决方案
常见的跨域解决方案: 跨域问题可以分为两种情况:前端跨域和后端跨域。以下是针对这两种情况的跨域解决方案: 前端跨域解决方案: JSONP: 适用于前端向不同域名下的服务器请求数据,通过添加回调函数名称来…...

分布式websocket解决方案
1、websocket问题由来 websocket基础请自行学习,本文章是解决在分布式环境下websocket通讯问题。 在单体环境下,所有web客户端都是连接到某一个微服务上,这样消息都是到达统一服务端,并且也是由一个服务端进行响应,所以不会出现问题。 但是在分布式环境下,我们很容易发现…...

奥威BI财务数据分析方案:借BI之利,成就智能财务分析
随着智能技术的发展,各行各业都走上借助智能技术高效运作道路,财务数据分析也不例外。借助BI商业智能技术能够让财务数据分析更高效、便捷、直观立体,也更有助于发挥财务数据分析作为企业经营管理健康晴雨表的作用。随着BI财务数据分析经验的…...

Android12之com.android.media.swcodec无法生成apex问题(一百六十三)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...

Xcode build和version
参考 一个叫做Version,一个叫做Build,(version是版本号,build是打正式包每次Archive时的都增加的值)这两个值都可以在Xcode中选中target,点击“Summary”后看到。 Version在plist文件中的key是“CFBundleSh…...

前端面试:【原型链】代码世界的家族传承
嗨,亲爱的代码探险家!在JavaScript的奇妙世界里,有一个令人惊叹的概念,那就是原型链。这个概念就像是代码世界的家族传承,允许对象之间分享属性和方法,让你的代码更加高效和灵活。 1. 什么是原型链…...

2D应用开发是选择WebGL 还是选择Canvas?
推荐:使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 在介绍WebGL和Canvas的区别和联系之前,需要先了解它们各自的定义和特点。 WebGL是一种基于标准HTML5的技术,用于在Web浏览器中实时渲染3D图形。它是由Khronos Group开发的一套…...

Android Framework 常见解决方案(20)UDP广播无效问题
1 现象描述和原理解读 该问题同时存在于android App和Framework系统中。最终效果是在Android系统中直接使用UDP广播无效,有意思的是有的android系统可以,有的Android 系统不行。然而该部分代码自己在Linux上测试时是有效的,代码不变…...

VINS-Mono中的边缘化与滑窗 (4)——VINS边缘化为何是局部变量边缘化?
文章目录 0.前言1.系统构建1.1.仿真模型1.2.第一次滑窗优化1.3.第二次全局优化 2.边缘化时不同的舒尔补方式2.1.边缘化时舒尔补的意义2.2.不同的边缘化方式 3.边缘化时不同的舒尔补方式实验验证3.1.全局schur的操作方式3.2.VIO或VINS中局部边缘化的方式3.3.两种方式和全局优化方…...

真·VB.NET彻底释放Interop.Excel对象
使用 Microsoft.Office.Interop.Excel 虽然有速度慢的缺点;但是作为自带引用,兼容性最好,而且是COM对象模型也很熟悉(Excel里直接录个宏,很方便把VBA代码转成VB.NET)。所以处理几百上千条的小数据时还是很方便的。 而 Microsoft.…...

记录hutool http通过代理模式proxy访问外面的链接
效果: 代码: public class TestMain {public static void main(String[] args){HttpRequest httpRequest HttpRequest.get("https://www.youtube.com").timeout(30000);httpRequest.setProxy(new Proxy(Proxy.Type.HTTP,new InetSocketAddre…...

Selenium 自动化 | 案例实战篇
Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器(如 Chrome、Opera 和 Microsoft Edge)中的工具,用于帮助开发人员调试和研究网站。 借助 Chrome DevTools,开发人员可以更深入地访问网站…...

前端技术栈es6+promise
let入门使用、 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>let 基本使用</title><script type"text/javascript">let name "hspedu教育";//老韩解读//1. conso…...

windows vscode使用opencv
1.windows vscode使用opencv 参考:https://blog.csdn.net/zhaiax672/article/details/88971248 https://zhuanlan.zhihu.com/p/402378383 https://blog.csdn.net/weixin_39488566/article/details/121297536 g -g .\hello_opencv.cpp -stdc14 -I E:\C-software\…...

json文件读取数据报错 AttributeError: ‘str‘ object has no attribute ‘items‘
trans_width_table表如下: {frozenset({2}): {3: 250, 2.5: 100, 1.5: 25, 2: 50, 1.8: 50, 2.75: 200, 5: 350, 4: 350, 2.3: 100, 4.5: 350, 3.5: 300}, frozenset({1, 3, 4, 5}): {2.5: 75, 2.75: 100, 1.5: 25, 4: 300, 3.5: 200, 4.5: 300, 3: 100, 5: 300, 2…...