- 博客(48)
- 收藏
- 关注
原创 多线程简单介绍
1.根本原因:操作系统对线程的调度是随机的,即抢占式执行2.多个线程修改同一个变量3.修改操作不是原子的,所谓的原子类似于数据库事务的原子性,当修改操作只对应到一个CPU指令,就说明该操作是原子的,即不会出现指令执行到一半就被调度走了的情况,上面的例子就不是原子的操作4.内存可见性5.指令重排序。
2026-04-06 21:30:08
405
原创 LangChain简单介绍
使用过⼀些原⽣大模型的⼈可能会发现⼀些问题,尽管⼤模型的在某些方⾯表现振奋人心,例如将其 当作搜索引擎去使用,LLM⽣成的答案可能要比其他搜索引擎查到的答案更符合你的预期,但要是在 复杂的场景下使用,如将LLM嵌⼊应用程序时却遭遇了全新难题,这里简单介绍6种主要问题。(注:《你一生的故事》是美国华裔作家特德·姜的作品,也是电影《降临》的原著)”技术在内部知识库进行检索,通过语义的形式(嵌入模型),会得到一些“参考答案”,然后把问题和答案一起发给大模型。:“请介绍一下《三体》的作者刘慈欣的其他作品。
2026-03-30 19:07:50
380
原创 JVM核心简单介绍
此时,引用计数都不为0,但是两个对象都无法使用,要使用第一个对象就得用第二个对象里的t来访问,要使用第二个对象里的t属性又得用第一个对象里的t属性来访问。3.每次访问到一个对象,都会把这个对象标记成“可达”,当完成所有的对象遍历之后,未被标记成“可达”的对象就会被释放,因为JVM本身是知道有多少个对象的。把新创建的对象放在伊甸区,如果新对象经过一轮GC活下来了,就通过复制放到幸存区,然后伊甸区再进行释放,此时复制的对象是比较少的。一次只使用一半,在清除垃圾前,把不是垃圾的对象拷贝到右边,然后把左边清除。
2026-03-29 21:55:42
444
原创 UDP、TCP
双端会进行数据的同步,TCP的同步指的是数据上的同步,b会保存a的关键信息,这里的关键信息就是端口号和IP地址。TCP会在接收方这里安排“接受缓冲区”,通过网卡读到的数据,先放到接收缓冲区里,根据序号来排列,序号小的在前面,大的在后面,先确保前面的数据到了,才解除阻塞,read开始读取,否则,read继续阻塞。这里的思路是,在传输之前,先计算一个校验和,然后把数据包和校验和一起发送,接收方在拿到数据包后再次计算一个校验和,与接收的校验和进行比较,若一致,则数据正确,反之,则直接丢弃。
2026-03-26 00:10:55
442
原创 HTTPS的工作过程
服务器向可信任的第三方机构申请证书,需要提交材料,包括服务器的域名之类内容,然后服务器依据进行审查,通过后给服务器颁发证书,类似于一个结构体,里面包含颁发证书的机构、证书的有效期、服务器的公钥,服务器的域名等,然后通过机构的私钥进行加密生成一个数字签名,实际上就是一个被加密的校验和。黑客自己生成一对公钥私钥,把客户端拿到的服务器换成自己的,这样就能拿到客户端的对称密钥,然后通过服务器的公钥加密,这样就能混入客户端与服务器的会话中。每个客户端的密钥都应该是不一样的,如果使用统一的密钥,黑客也就容易拿到了。
2026-03-22 21:36:56
443
原创 网络编程套接字
对于数据报来说,可以简单的理解为,传输数据是⼀块⼀块的,发送⼀块数据假如100个字节,必须一次发送,接收也必须⼀次接收100个字节,而不能分100次,每次接收1个字节。对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的 情况下,是无边界的数据,可以多次发送,也可以分开多次接收。对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且⼀次发送全部 数据报,⼀次接收全部的数据报。以上只是运用回显服务器进行简单的演示,只是返回了客户端的请求。
2026-03-21 22:42:53
275
原创 TCP/IP五层模型
要了解这个大问题,得先知道一些前缀问题。协议分层是将计算机网络通信过程分解为多个不同层次、各自独立又相互协作的结构化方法。举个例子,比如打电话的过程。每层之间有自己的协议,比如语言层可以是汉语、英语,设备层则有自己独有的语言,语言层调用设备的接口。但实际网络的传输过程比这个复杂得多。
2026-03-21 12:16:39
471
原创 哈希冲突的解决方法之哈希桶
开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子 集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。值得注意的是扩容方法,以1和11为例,原数组长度为10,翻倍后为20,原本11%10=1,现在。代码实现以纯数字为例子,实际上hash的key的类型是不固定的,这里只是为了展示过程。开散列,可以认为是把一个在大集合中的搜索问题转化为在小集合中做搜索了。
2026-03-19 21:40:35
42
原创 二叉搜索树
3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.right。3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.left。2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.right。2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.left。1.如果树为空,直接插入即可。
2026-03-19 15:39:26
260
原创 归并排序的简单实现
其实 换成 > ,结果也是一样的。但是如果真的出现向相等的情况,使用 > 的话,代码会多执行,从效率上考虑,选择 >= 时比较好的。1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。合并的思路是把每个小组比较后放入一个新的临时数组里,然后再赋值即可。找到mid,然后分解即可,直到 left == right。2. 时间复杂度:O(N*logN)分为两个大步骤,分解和合并。3. 空间复杂度:O(N)
2026-03-18 16:00:05
91
原创 快速排序非递归实现
前面的步骤省略,当left与right相遇的时候,依次将0 、4 、6、9入栈,因为栈的性质,以及入栈的顺序,弹出的时候从右往左。排序的思路是不变的,这里采用挖坑法,不用递归实现,用栈实现。start为6 ,end为9再次排序即可。时间复杂度为 O( N *log N)
2026-03-17 20:52:57
53
原创 快速排序的简单实现
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其为:任取待排序元素序列中的某元 素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有 元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
2026-03-17 17:04:11
349
原创 冒泡排序的简单实现
其实,这个排序已经是优化过的了,因为第二层循环中 j < arr.length - i - 1,这里 减 i 是因为,前面已经排过序了, 不需要再排一次。但有一种情况是,可能数组已经有序了,但是程序并没有执行完毕。冒泡排序的过程很简单,就是不断交换,这里不再演示过程。若并没有发生交换,说明已经有序了,直接结束循环即可。1. 冒泡排序是一种非常容易理解的排序。
2026-03-16 17:11:13
85
原创 直接选择排序
有一种情况是left 本身已经指向最大的元素了,然后minIndex 依旧与它交换,然而最大值maxIndex已经确定完毕,right已经修改了,加入这行代码可以解决。因为 array[ j ] < array[ mindindex] 所以把 j 的值赋给mindindex,j++j从 i + 1 开始,mindIndex 记录值小于 i 下标所对应值的下标,初始值为i。这个代码的时间复杂度是 O( N^ 2),效率很低。然后交换i 与 mindIndex 所对应的值。然后重复上述过程即可。
2026-03-16 15:51:25
86
原创 希尔排序的简单实现
希尔排序实际上是对直接插入排序的优化,直接插入排序的特点是越有序,排的越快,那么实际上希尔排序是将数组进行分组,满足 i - j = gap然而,不论分多少组,最后一组的gap必须是1。
2026-03-15 17:26:34
75
原创 直接插入排序的简单实现
i 从 1 开始,j 从 i - 1 开始把 array[ i ] 的值记录在 temp 里当array[ j ] 的值大于 temp,将array[ j ] 的值赋给 array[ j + 1],然后 j - -当 array[ j ] 的值小于 temp 时,把temp 的 值 赋给array[ j + 1],还有一种情况是当j 为 0,然后后续重复这个过程。
2026-03-15 16:27:58
106
原创 使用PriorityQueue创建大小堆,解决TOPK问题
要维护一个长度为k的小根堆,堆顶是堆里最小的数,然后开始比较,将大于堆顶的数入队,内部会进行向上调整,依次将剩下的数据处理。本例是找最大的k个数,要维护一个小根堆,反之,找最小的k个数,就维护一个大根堆。2. 用户也可以选择使用比较器对象,如果用户插入自定义类型对象时,必须要提供一个比较器类,让该类实现 Comparator接口并覆写compare方法。1. Comparble是默认的内部比较方式,如果用户插入自定义类型对象时,该类对象必须要实现Comparble接 口,并覆写compareTo方法。
2026-03-15 15:23:29
45
原创 用堆模拟实现优先级队列(Java)
综上实现为大根堆,若想变成小根堆,只需变动向上、向下调整的部分内容即可。一般在弹出一个元素后,会对整体进行向下调整。添加扩容机制,入队后进行向上调整。在入元素后进行向上调整。
2026-03-14 20:37:30
42
原创 顺序表的实现(Java)
默认是直接在尾部添加,也可指定位置添加,添加前会进行空间判断,空间不够会进行扩容,从后向前添加是为了提高效率。顺序表使用数组实现的,size是数组的实际数据的长度,提供了默认构造和带参数的构造。
2026-03-13 15:56:43
61
原创 商城系统自动化测试报告
环境层:利用自动化管理驱动,保证测试环境快速搭建和稳定运行。工具层:利用各种Utils封装通用操作,提高代码复用性和开发效率。用例层:利用pytest和fixture来管理测试用例的生命周期和依赖,实现"高内聚、低耦合"的测试结构。后续测试用例的设计实现模块化,用例之间做到关联性低,模拟用户使用商城系统的核心流程。
2026-03-08 18:05:44
321
原创 网页聊天室自动化测试报告
所有的测试用例设计以及代码的实现都与预期相符合,不同场景下各个方法的实现尽量满足“高内聚、低耦合”的标准。页面自动化具备截图功能,接口自动化则有日志,都可以在发生问题时即使回溯问题,通过模块化设计和场景化用例,有效验证了用户从注册到发送信息的核心流程。
2026-02-26 17:25:16
664
原创 Thread类的基本用法(上)
1.继承类这里中间运行的代码,需要抛出异常。然后创建MyThread的实例,并执行2.实现接口然后创建Thread实例,将Runnable对象作为参数。这里也可以写成后面的使用方法不变。3.使用匿名内部类创建Thread子类对象实际上就是第一种方法的变形。4.匿名内部类创建Runnable子类对象后面依旧需要创建Thread实例化,将Runnable作为对象参数传入。5.使用lambda表达式创建子类这也是最简单最常用的方法。
2025-09-10 21:54:01
220
原创 进程与线程的区别与联系
1.进程是一个动态的概念,它代表的是程序在某个数据集上的一次执行活动。2.它是操作系统进行资源分配的和保护的独立单位。3.每个进程可以抽象成一个结构体,里面包含了管理该进程所需的全部信息。比如进程ID之类。
2025-09-10 20:49:26
231
原创 Java中的String类
String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照如下规则进行比较,比如: s1.equals(s2)与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值。1. 字符"|","*","+"都得加上转义字符,前面加上 "\\" .2. 而如果是 "\" ,那么就得写成 "\\\\" .
2025-05-28 16:44:39
619
原创 Java自定义类的clone
方法的,而它又是所有自定义类的父类,理论上是可以调用的,但当我们直接像上面一样使用时是会直接报错的。而因为使用的 Object 类会发生向下转型,我们在测试类中调用时要进行强制类型转换,的学习,在使用父类方法的时候是要对方法重写,这时候需要接受一个空的接口(自动生成)、通过结果可以看出,这里的拷贝只是将。这样就可以实现拷贝。
2025-05-17 13:45:00
249
原创 认识类和对象(下)
为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。基本规则在文件的最上方加上一个 package 语句指定该代码在哪个包中.
2025-05-07 20:56:56
956
原创 认识类和对象(上)
// 创建类field;// 字段(属性) 或者 成员变量method;// 行为 或者 成员方法class为定义类的关键字,ClassName为类的名字,{}中为类的主体。类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。// 品牌// 型号// 重量// 长// 宽// 高// 颜色public void washClothes(){ // 洗衣服。
2025-05-07 17:05:49
667
原创 string类(C++)
在使用string类时,必须包含#include头文件以及using namespace std。C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。到C++阶段,基本上很少有人继续使用C语言阶段的东西。String就是一个很方便的工具。
2024-08-01 15:57:09
747
原创 文件的基本内容
程序文件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows 环境后缀为.exe)。文件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或 者输出内容的⽂件。
2024-04-02 15:57:57
1638
1
原创 编译与链接
翻译环境可将源代码转变成机械指令。它由和三个过程。大体流程如下:⼀个C语⾔的项⽬中可能有多个 .c ⽂件⼀起构建,那多个 .c ⽂件如何⽣成可执⾏程序呢?• 多个.c⽂件单独经过编译器,编译处理⽣成对应的⽬标⽂件。• 注:在Windows环境下的⽬标⽂件的后缀是 .obj ,Linux环境下⽬标⽂件的后缀是 .o• 多个⽬标⽂件和链接库⼀起经过链接器处理⽣成最终的可执⾏程序。• 链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库。
2024-03-31 21:53:58
1490
1
原创 malloc、calloc、realloc、free的使用
这个函数向内存申请⼀块连续可⽤的空间,并返回指向这块空间的指针。• 如果开辟成功,则返回⼀个指向开辟好空间的指针。• 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查。• 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使⽤的时候使⽤者⾃ ⼰来决定。首先,malloc后的是字节数,因为是一个无类型的指针,所以我们要将其进行强制类型转换成类型,方便后续操作。
2024-03-23 20:14:36
912
原创 strlen,strcpy, strcat, strcmp的使用以及模拟实现
字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包 含 '\0' )。使用strlen必须包含头文件。对其进行模拟实现的话,可以从它的原理入手。
2024-03-23 11:15:56
260
原创 整数和浮点数在内存中的存储
整形数据在内存中存放的是补码。原因在于,使⽤补码,可以将符号位和数值域统⼀处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是 相同的,不需要额外的硬件电路。
2024-03-18 22:36:21
414
1
原创 指针的(最)基本内容(上)
计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数 据也会放回内存中,每个内存单元都有⼀个编号,有了这个内存单元的编 号,CPU就可以快速找到⼀个内存空间,在计算机中我们 把内存单元的编号也称为地址。指针。简单的说,指针其实就是地址。
2024-03-12 22:08:59
384
原创 左旋字符串
strcpy ( a , b )的作用是将b里的内容拷贝进a里如果a里面有内容会覆盖,而strncat(a,b)也是将b的内容拷贝进a里,但不同的是他不会覆盖。先把第一个字符放进 temp 里,然后让后一个字符与前一个交换,最后再将temp的字符放回,达到交换的目的。注意:在VS里使用此库函数要加:#define _CRT_SECURE_NO_WARNINGS。这里用 leftaround 实现目的,然后用Print打印出结果。题目:将字符串“ABCDE”左旋2位,变成“CDEAB”。
2024-02-01 14:58:10
402
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅