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

JUC并发编程高级篇第四章之ThreadLocal(人手一份,天下安)

文章目录

  • 1、ThreadLocal的简介
    • 1.1、常见的面试题(也是本次的讲解的内容)
    • 1.2、什么是ThreadLocal
    • 1.3、ThreadLocal的所用
    • 1.4、没有出现ThreadLocal前后的变化
    • 1.5、ThreadLocal代码示例
    • 1.6、阿里巴巴对ThreadLocal的使用要求
    • 1.7、ThreadLocal的源码分析
  • 2、ThreadLocal弱引用问题
    • 2.1、什么是内存泄露?
    • 2.2、什么是强/软/弱/虚 引用?
    • 2.3、ThreadLocal为什么要使用软引用
      • 2.3.1、如果使用强引用会内存泄漏吗?
      • 2.3.2、如果使用弱引用会内存泄漏吗?
      • 2.3.3、出现内存泄漏的真实原因
      • 2.3.4、JDK为什么最后选择弱引用呢?
      • 2.3.4、清楚脏entry
      • 2.3.5、为什么ThreadLocal有自动清理entry的机制,我们还需要注意调用remove
  • 3、ThreadLocalMap 没有Map中的链表,如何解决hash冲突?
    • 3.1、构造方法
    • 3.2、set方法
  • 4、ThreadLocal的最佳实践
  • 5、ThreadLocal的总结

1、ThreadLocal的简介

1.1、常见的面试题(也是本次的讲解的内容)

  1. ThreadLocal当中ThreadLocalMap的数据结构和关系
  2. ThreadLocal的key是弱引用,为什么
  3. ThreadLocal的内存泄露
  4. ThreadLocal为什么最后加入了remove方法

1.2、什么是ThreadLocal

ThreadLocal提供线程局部变量。这些变量与正常的变量不同,因为每一个线程在访问ThreadLocal实例的时候(通过其getiset方法)都有自己的、独立初始化的变量副本。ThreadLocal实例通常是类中的私有静态字段,使用它的目的是希望将状态(例如,用户ID或事务ID)与线程关联起来

1.3、ThreadLocal的所用

  • 实现每一个线程都有自己专属的本地变量副本(自己用自己的变量禧麻烦别人,不和其他人共享,人人有份,人各一份),
  • 主要解决了让每个线程绑定自己的值,通过使用get()和.set()方法,获取默认值或将其值更改为当前线程所存的副本的值从而避免了线程安全问题,比如我们之前讲解的8锁案例,资源类是使用同一部手机,多个线程抢夺同一部手机使用,假如人手一份是不是天下太平

特别注意:ThreadLocal设计的目的是帮助当前线程有属于自己的变量,并不是为了解决并发或共享变量的问题

1.4、没有出现ThreadLocal前后的变化

  • 没出现ThreadLocal之前, 不管是sync/local/cas 他们都是多个线程抢占一个资源
  • 出现ThreadLocal之后,每个线程都有属于自己的资源

1.5、ThreadLocal代码示例

需求1:: 5个销售卖房子,集团高层只关心销售总量的准确统计数,按照总销售额统计,方便集团公司给部分发送奖金

public class DeadlockExample {//5个销售卖房子,集团高层只关心销售总量的准确统计数,按照总销售额统计,方便集团公司给部分发送奖金public static void main(String[] args) throws InterruptedException {Hourse hourse = new Hourse();CountDownLatch countDownLatch = new CountDownLatch(5);for (int i = 0; i < 5; i++) {new Thread(()->{int size = new Random().nextInt(5) + 1;System.out.println(Thread.currentThread().getName()+"线程卖了"+size+"套");for (int j = 0; j < size; j++) {hourse.saleHourse();}countDownLatch.countDown();},String.valueOf(i)).start();}countDownLatch.await();System.out.println("一共卖了"+hourse.getSaleCount());}
}class Hourse {int saleCount = 0;public synchronized void saleHourse() {++saleCount;}public int getSaleCount() {return saleCount;}
}3线程卖了11线程卖了52线程卖了54线程卖了40线程卖了5套
一共卖了20

需求2: 5个销售卖完随机数房子,各自独立销售额度,自己业绩按提成走,分灶吃饭,各个销售自己动手,丰衣足食

public class DeadlockExample {//5个销售卖房子,集团高层只关心销售总量的准确统计数,按照总销售额统计,方便集团公司给部分发送奖金public static void main(String[] args) throws InterruptedException {Hourse hourse = new Hourse();CountDownLatch countDownLatch = new CountDownLatch(5);for (int i = 0; i < 5; i++) {new Thread(() -> {int size = new Random().nextInt(5) + 1;for (int j = 0; j < size; j++) {hourse.saleSyncHourse();hourse.saleThreadLocal();}System.out.println(Thread.currentThread().getName() + "线程卖了" + hourse.saleVolume.get() + "套");countDownLatch.countDown();}, String.valueOf(i)).start();}countDownLatch.await();System.out.println("一共卖了" + hourse.getSaleCount());}
}class Hourse {ThreadLocal<Integer> saleVolume = ThreadLocal.withInitial(() -> 0);int saleCount = 0;public int getSaleCount() {return saleCount;}public synchronized void  saleSyncHourse(){++saleCount;}public void saleThreadLocal(){saleVolume.set(1+saleVolume.get());}
}4线程卖了41线程卖了32线程卖了13线程卖了20线程卖了1套
一共卖了11

1.6、阿里巴巴对ThreadLocal的使用要求

在这里插入图片描述
原因:因为实际开发的场景中, 我们都是使用线程池,此时有些线程就会存在反复复用的情况,如果没有清理线程的ThreadLocal变量,则到了线程复用的时候,可能还是携带者过去的老数据,导致业务逻辑混乱

1.7、ThreadLocal的源码分析

结论1:Thread类包含ThreadLocal,ThreadLocal包含了ThreadLocalMap
在这里插入图片描述
结论2:ThreadLocalMap中包含了继承弱引用的Entry
在这里插入图片描述
结论3:ThreadLocalMap其实就是以ThreadLocal为key ,任意对象obejct为valu的entry
在这里插入图片描述

2、ThreadLocal弱引用问题

谈到这个问题,我们需要先回归下基础知识

2.1、什么是内存泄露?

不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。

2.2、什么是强/软/弱/虚 引用?

强引用(Java默认new一个对象就是强引用)

  • 当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。
class MyClass{@Overrideprotected void finalize() throws Throwable {System.out.println("我被调用了,我快要死了");}
}
public class ReferenceDemo {public static void main(String[] args) throws InterruptedException {MyClass myClass = new MyClass();System.out.println("gc object "+myClass);myClass =null;//主动触发gcSystem.gc();Thread.sleep(500);System.out.println("gc object "+myClass);}
}gc object com.tvu.deathLock.MyClass@43556938
我被调用了,我快要死了
gc object null

软引用

  • 当系统内存充足时它不会回收
  • 当系统内存不充足时它会回收
  • 软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收!
class MyClass{@Overrideprotected void finalize() throws Throwable {System.out.println("我被调用了,我快要死了");}
}
public class ReferenceDemo {public static void main(String[] args) throws InterruptedException {SoftReference<MyClass> myClassSoftReference = new SoftReference<>(new MyClass());System.gc();System.out.println("gc after:" + myClassSoftReference.get());}
}gc 内存够用 after:com.tvu.deathLock.MyClass@43556938

弱引用

  • 弱引用需要用java.lang.ref.WeakReference类来实现,它比软引用的生存期更短,
  • 对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,都会回收该对象占用的内存。
    假如有一个应用需要读取大量的本地图片,如果每次读取图片都从硬盘读取则会严重影响性能,
    如果一次性全部加载到内存中又可能造成内存溢出。此时使用软引用可以解决这个问题。设计思路是:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题。Map<String, SoftReference<Bitmap>>imageCache = new HashMap<String, SoftReference<Bitmap>>();

虚引用

  • 虚引用需要java.lang.ref.PhantomReference类来实现,顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
  • PhantomReference的get方法总是返回null
  • 虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被finalize以后,做某些事情的通知机制。PhantomReference的get方法总是返回null,因此无法访问对应的引用对象。
  • 换句话说,设置虚引用关联对象的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理,用来实现比finalize机制更灵活的回收操作

2.3、ThreadLocal为什么要使用软引用

2.3.1、如果使用强引用会内存泄漏吗?

在这里插入图片描述
1:上面ThreadLocalRef he CurrentThreadRef 分别代码ThreadLocal和CurrentThread的引用,他们分别存储在栈里面

2.3.2、如果使用弱引用会内存泄漏吗?

在这里插入图片描述

2.3.3、出现内存泄漏的真实原因

在这里插入图片描述

2.3.4、JDK为什么最后选择弱引用呢?

在这里插入图片描述

2.3.4、清楚脏entry

ThreadLocal 再进行set/get/remove的时候都对空的entry进行检查和清除;

set()

进行set的时候,遍历节点元素检测元素为空
在这里插入图片描述

get()
在这里插入图片描述
在这里插入图片描述
remove
在这里插入图片描述

2.3.5、为什么ThreadLocal有自动清理entry的机制,我们还需要注意调用remove

虽然set和get方法会帮我们清理entry为null的值,但是如果一个ThreadLocal对象被创建后,在某个线程中调用了set方法设置了一个值,但是在后续的代码中没有调用get或remove方法来清除这个值,那么这个值就会一直存在于这个ThreadLocal对象中,直到线程结束。如果这个线程是一个长期运行的线程,那么这个值就会一直存在于内存中,占用一定的空间,从而导致内存泄漏。

3、ThreadLocalMap 没有Map中的链表,如何解决hash冲突?

3.1、构造方法

     ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {table = new Entry[INITIAL_CAPACITY];//计算索引int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);table[i] = new Entry(firstKey, firstValue);//entry存储的个数,因为是构造函数,所以是1size = 1;setThreshold(INITIAL_CAPACITY);}===========================threadLocalHashCode 相关代码======================================private final int threadLocalHashCode = nextHashCode();private static int nextHashCode() {//HASH_INCREMENT 是为了让hash均匀的分布,尽量避免return nextHashCode.getAndAdd(HASH_INCREMENT);}public final int getAndAdd(int delta) {return unsafe.getAndAddInt(this, valueOffset, delta);}public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;}==========================INITIAL_CAPACITY - 1)============================================学过HashMap的都知道,容量被设置为2的n次方,当进行-1的时候,此时2进制的最后一位都是1,此时相当于提高了效率,比如此时10进行4预算,此时如果为1的话,后面基本上就不用看啦

3.2、set方法

private void set(ThreadLocal<?> key, Object value) {// We don't use a fast path as with get() because it is at// least as common to use set() to create new entries as// it is to replace existing ones, in which case, a fast// path would fail more often than not.Entry[] tab = table;int len = tab.length;//计算索引,刚刚分析过啦int i = key.threadLocalHashCode & (len-1);//使用线性查找法查找元素for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {ThreadLocal<?> k = e.get();//threadlocal对应的key存在,覆盖之前的值if (k == key) {e.value = value;return;}//如果不存在,说明被回收啦,当前数据中entry是一个陈旧的元素if (k == null) {//用新元素代替旧元素,这个方法进行了不少清理垃圾的动作,防止内存泄漏replaceStaleEntry(key, value, i);return;}}//如果key不存在,并且没有找到陈旧的元素,则在空位置上进行新创建新的entrytab[i] = new Entry(key, value);int sz = ++size;//清除e.get() = null的元素//这种数据关联key关联的对象,已经被回收啦,所以entry(table (index)可以设置为null//如果没有清楚任何的entry,并且当前的使用量达到了负载银子,那么进行rehashif (!cleanSomeSlots(i, sz) && sz >= threshold)rehash();}

在这里插入图片描述

总结:

和HashMap的最大的不同在于,ThreadLocalMap结构非常简单,没有next引用,也就是说ThreadLocalMap中解决Hash冲突的方式并非链表的方式,而是采用线性探测的方式,所谓线性探测,就是根据初始key的hashcode值确定元素在table数组中的位置,如果发现这个位置上已经有其他key值的元素被占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置。

ThreadLocalMap解决Hash冲突的方式就是简单的步长加1或减1,寻找下一个相邻的位置。

/*** Increment i modulo len.*/
private static int nextIndex(int i, int len) {return ((i + 1 < len) ? i + 1 : 0);
}/*** Decrement i modulo len.*/
private static int prevIndex(int i, int len) {return ((i - 1 >= 0) ? i - 1 : len - 1);
}

显然ThreadLocalMap采用线性探测的方式解决Hash冲突的效率很低,如果有大量不同的ThreadLocal对象放入map中时发送冲突,或者发生二次冲突,则效率很低。

所以这里引出的良好建议是:每个线程只存一个变量,这样的话所有的线程存放到map中的Key都是相同的ThreadLocal,如果一个线程要保存多个变量,就需要创建多个ThreadLocal,多个ThreadLocal放入Map中时会极大的增加Hash冲突的可能

4、ThreadLocal的最佳实践

  • 1.尽量初始化 ThreadLocal tl = ThreadLocal.withInitial(()->“1”);
  • 2.建议把ThreadLocal修饰为static (ThreadLocal能够实现数据的隔离,不在于它自己本身,而是Thead的ThreadLocalMap所以ThreadLocal可以只初始化一次,只分配一块存储空间就行了,没必要作为成员变量多次被初始化)
  • 3.用完记得remove

5、ThreadLocal的总结

  • ThreadLocal并不解决线程间共享数据的问题
  • ThreadLocal适用于变量在线程间隔离且在方法间共享的场景
  • ThreadLocal通过隐式的在不同线程内创建独立实例副本避免了实例线程安全的问题
  • 每个线程持有一个只属于自己的专属Map弃维护了ThreadLocal对象与具体实例的映射,该Map由于只被持有它的线程访问,故不存在线程安全以及锁的问题
  • ThreadLocalMap的Entry对ThreadLocal的引用为弱引用,避免了ThreadLocal对象无法被回收的问题
  • 都会通过expungeStaleEntry,cleanSomeSlots,replaceStaleEntry这三个方法回收键为null 的Entry对象的值(即为具体实例)以及Entry对象本身从而防止内存泄漏,属于安全加固的方法
  • 群雄逐鹿起纷争,人各一份天下安

相关文章:

JUC并发编程高级篇第四章之ThreadLocal(人手一份,天下安)

文章目录1、ThreadLocal的简介1.1、常见的面试题(也是本次的讲解的内容&#xff09;1.2、什么是ThreadLocal1.3、ThreadLocal的所用1.4、没有出现ThreadLocal前后的变化1.5、ThreadLocal代码示例1.6、阿里巴巴对ThreadLocal的使用要求1.7、ThreadLocal的源码分析2、ThreadLocal…...

dump 定位分析

在缺少pdb的时候如何分析dump&#xff1f; windbgidaWindbg定位崩溃位置 通过windbg打开dump&#xff0c;并且分析dump !analyze -v 分析&#xff1a; 分析dump&#xff1a; !analyze -v错误原因&#xff1a;读取空指针错误线程&#xff1a;00001e04&#xff0c;可通过命令…...

(十二)排序算法-插入排序

1 基本介绍 1.1 概述 插入排序属于内部排序法&#xff0c;是对于欲排序的元素以插入的方式找寻该元素的适当位置&#xff0c;以达到排序的目的。 插入排序的工作方式非常像人们排序一手扑克牌一样。开始时&#xff0c;我们的左手为空并且桌子上的牌面朝下。然后&#xff0c;…...

elasticsearch 认知

1.大数据领域需要解决以下三个问题 如何存储数据 传统的关系数据库&#xff08;MySQL、Oracle、和Access等&#xff09;主导了20世纪的数据存储模式&#xff0c;但当数据量达到太字节级&#xff0c;甚至拍字节级时&#xff0c;关系型数据库表现出了难以解决的瓶颈问题。为了解决…...

《人体地图》笔记

《人体地图》 坂井建雄 著 孙浩 译 腹部通向大腿的隧道 腹部与大腿的分界点是大腿根部&#xff0c;即是腹股沟。 腹壁肌肉连结在腹股沟韧带上&#xff0c;腹壁肌肉包括三层&#xff0c;分别为腹外斜肌、腹内斜肌和腹横肌&#xff0c;每块肌肉都有一个张开的小孔&#xff0c;…...

java基础集合面试题

什么是集合 集合就是一个放数据的容器&#xff0c;准确的说是放数据对象引用的容器 集合类存放的都是对象的引用&#xff0c;而不是对象的本身 集合类型主要有3种&#xff1a;set(集&#xff09;、list(列表&#xff09;和map(映射)。 集合的特点 集合的特点主要有如下两点&…...

Vue学习-Vue入门

Vue学习 一、Vue入门 1、 引入Vue Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库…...

【项目】bxg基于SaaS的餐掌柜项目实战(2023)

基于SaaS的餐掌柜项目实战 餐掌柜是一款基于SaaS思想打造的餐饮系统&#xff0c;采用分布式系统架构进行多服务研发&#xff0c;共包含4个子系统&#xff0c;分别为平台运营端、管家端&#xff08;门店&#xff09;、收银端、小程序端&#xff0c;为餐饮商家打造一站式餐饮服务…...

灌区流量监测设备-中小灌区节水改造

系统概述 灌区信息化管理系统主要对对灌区的水情、雨情、土壤墒情、气象等信息进行监测&#xff0c;对重点区域进行视频监控&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;实现了信息的测量、统计、分析、控制、调度等功能。为灌区管理部门科学决策提供了依据&#xf…...

SpringBoot2核心功能 --- 指标监控

一、SpringBoot Actuator 1.1、简介 未来每一个微服务在云上部署以后&#xff0c;我们都需要对其进行监控、追踪、审计、控制等。SpringBoot就抽取了Actuator场景&#xff0c;使得我们每个微服务快速引用即可获得生产级别的应用监控、审计等功能。 <dependency><gro…...

python实战应用讲解-【numpy数组篇】常用函数(三)(附python示例代码)

目录 Python numpy.repeat() Python numpy.tile() Python numpy.asarray_chkfinite() Python numpy.asfarray() Python numpy.asfortranarray() Python numpy.repeat() Python numpy.repeat()函数重复数组中的元素 – arr. 语法 : numpy.repeat(arr, repetitions, axis …...

DIN论文翻译

摘要 在电子商务行业&#xff0c;利用丰富的历史行为数据更好地提取用户兴趣对于构建在线广告系统的点击率(CTR)预测模型至关重要。关于用户行为数据有两个关键观察结果&#xff1a;i) 多样性(diversity)。用户在访问电子商务网站时对不同种类的商品感兴趣。ii) 局部激活(local…...

python列表,元组和字典

1、python列表 1.1.列表的定义 list是一种有序的集合、基于 链表实现,name[ ] ,全局定义:list2list([ ])。 1.2下标索引 python不仅有负索引也有正索引。正索引从0开始,负索引从-1开始。这两个可以混用,但指向还是那个位置 a[0]a[-9]//length为10的数组a1.3列表的切片 列表可…...

300元左右的蓝牙耳机哪个好?300左右音质最好的蓝牙耳机

无线耳机是人们日常生活中必不可少的设备&#xff0c;无论是听音乐化石看电影都能获得身临其境的感觉&#xff0c;由于科技真在发展中&#xff0c;不断地的发生变化&#xff0c;百元价位就可以感受到不错的音色&#xff0c;下面小编整理了几款300左右音质表现不错的蓝牙耳机。 …...

【消息队列】聊一下生产者消息发送流程

消息发送流程 1.生产者main线程调用send发送消息&#xff0c;先走拦截器&#xff0c;然后会将消息进行序列化&#xff0c;然后选择对应的分区器&#xff0c;将消息发送到RecordAccumulator中&#xff0c;默认是32m 2.Sender线程会异步读取&#xff0c;要不数据达到batch的大小 …...

特斯拉和OpenAI的加持,马斯克简直人生赢家

赢家已定 商人行事&#xff0c;最重要的因素之一是利益驱动。这里&#xff0c;最服“马斯克”。 以马斯克为首的特斯拉公司周日宣布&#xff0c;将在上海新建一家超级工厂&#xff0c;专门生产该公司的储能产品Megapack。签约的特斯拉储能超级工厂项目也是该公司在美国本土以…...

优维低代码:第三方接口接入

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 连载…...

SQL 177. 第N高的薪水

SQL 177. 第N高的薪水数据需求解决方法1方法2题目 &#xff1a; https://leetcode.cn/problems/nth-highest-salary/ 数据 Create table If Not Exists Employee (Id int comment 主键列, Salary int comment 工资 );Truncate table Employee;insert into Employee (id, sala…...

14天手撸交互式问答数字人直播教程-课程计划

一、课程计划 二、时间安排 第01天&#xff1a;交互式问答数字人发展现状 从一个真实案例开始&#xff0c;介绍当前主流的交互式数字人平台&#xff0c;需求和应用场景&#xff0c;引入交互式数字人的交互流程和关键技术。后续整个直播系列的内容安排。 第02天&#xff1a;音…...

spring boot3.0新特性Http客户端远程调用

1、安装依赖 <!-- For reactive support --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>2、项目结构 3、新建配置类WebConfig package com.exa…...

查询联系:多表查询 - 1

查询所有学生的 name&#xff0c;以及该学生在 score 表中对应的 c_no 和 degree 。 SELECT no, name FROM student; ---------------- | no | name | ---------------- | 101 | 曾华 | | 102 | 匡明 | | 103 | 王丽 | | 104 | 李军 | | 105 | 王芳…...

「Bug」OpenCV读取图像为 None 分析

头一次遇到 OpenCV 无法读取图像&#xff0c;并且没有任何提示&#xff0c;首先怀疑的就是中文路径&#xff0c;因为大概率是这个地方出错的&#xff0c;但是修改完依旧是None&#xff0c;这就很苦恼了&#xff0c;分析了下出现None的原因&#xff0c;大概有以下三种情况&#…...

EVO——视觉里程计/SLAM轨迹评估工具

EVO——SLAM轨迹精度评估软件 EVO简介 evo是一款用于视觉里程计VIO和slam轨迹评估 Python 包&#xff08;Linux / macOS / Windows / ROS&#xff09;。能够绘制轨迹&#xff0c;评估轨迹与真值的误差。支持多种数据集的轨迹格式&#xff08;TUM、KITTI、EuRoC的Mav、ROSbag&…...

TCP为什么要三次握手,而不是两次或四次?

文章目录TCP为什么要三次握手&#xff0c;而不是两次或四次&#xff1f;三次握手才可以阻止重复历史连接的初始化&#xff08;主要原因&#xff09;同步双方初始序列号避免资源浪费小结TCP为什么要三次握手&#xff0c;而不是两次或四次&#xff1f; TCP连接时用于保证可靠性和…...

git 命令:工作日常使用

git start 存储分支 git start list 查看所有存储 拉取最新master 合并到自己分支&#xff1a; git remote add [远程名称] [远程仓库链接] //关联(添加)远程仓库; 第一步&#xff1a;查看分支在哪里&#xff0c;是自己的吗&#xff0c;添加暂存区&#xff0c;添加到仓…...

Http和Https

http和https的区别 开销&#xff1a;HTTPS 协议需要到 CA 申请证书&#xff0c;一般免费证书很少&#xff0c;需要交费&#xff1b;资源消耗&#xff1a;HTTP 是超文本传输协议&#xff0c;信息是明文传输&#xff0c;HTTPS 则是具有安全性的 ssl 加密传输协议&#xff0c;需要…...

【计算机网络复习】第三章 传输层 2

UDP: 用户数据报协议 u 简单高效的传输层协议 u 提供“尽力而为(best effort)”服务 UDP数据报可能丢失 接收的顺序可能与发送顺序不一致 u 无连接协议 在发送数据之前&#xff0c;发送端和接收端没有握手(handshaking ) 每个UDP数据报都是独立的&#xff0c;…...

你真的会自动化测试?自动化测试技术选型抉择

自动化测试框架 在学习自动化测试或者实践自动化测试时&#xff0c;我们一定会对一个名词不陌生&#xff0c;那就是“自动化测试框架”&#xff0c;而有些人也将Selenium、Appium这样的工具也称之为“自动化测试框架”&#xff0c;那么到底自动化测试框架如何理解呢&#xff1…...

【id:31】【20分】A. Point(类与构造)

题目描述 下面是一个平面上的点的类定义&#xff0c;请在类外实现它的所有方法&#xff0c;并生成点测试它。 输入 测试数据的组数 t 第一组测试数据点p1的x坐标 第一组测试数据点p1的y坐标 第一组测试数据点p2的x坐标 第一组测试数据点p2的y坐标 .......... 输出 输出…...

ASM字节码处理工具原理及实践(二)

0. 相关分享 ASM字节码处理工具原理及实践&#xff08;一&#xff09; 上一篇讲了ASM的简介、导入&#xff0c;以及字节码文件结构&#xff0c;并给出了ASM通过ClassVisitor对class进行访问的基础实战。本篇将进入MethodVisitor&#xff0c;尝试对方法进行访问、生成、转换。…...