自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(130)
  • 收藏
  • 关注

原创 hello-agents-chapter1-初识智能体

在本案例中,我们将实现一个智能旅行助手Agent,其工作流程如下:1.接收用户请求:查询某地天气,并根据天气推荐景点;2.调用天气API(wttr.in API)获取目标城市天气3.根据天气,调用景点搜索API,推荐合适的景点;4.全程根据LLM(Large Language Model,大语言模型)决策下一步该做什么,最终返回结果给用户。基本流程是:用户请求 -> LLM 思考决策 -> 调用工具 -> 获取结果 -> LLM判断是否结束 -> 返回最终答案。

2026-03-29 22:09:14 268

原创 Redis主从复制

主从复制的三种模式:全量复制、基于长连接的命令传播、增量复制。建立连接后,由于双方完全不了解彼此,因此要进行全量复制。在全量复制中,生成 RDB 文件和发送 RDB 文件都是耗时的操作。当从服务器数量较多,应当让一些从服务器也拥有自己的从服务器,分摊主服务器的压力,让其能够专注于处理客户端的命令。在全量复制的过程中,如果有新的写操作命令,会先放到 repl_backlog_buffer 缓冲区中,再复制一份到 replicate buffer 缓冲区中,然后再发送给从服务器。

2026-03-26 16:56:29 410

原创 6-MySQL

点击上方的Database,左侧就弹出了Database Explorer,点击加号 -> Data Source -> MySQL,User就是root,接着输入你设置的密码,选择下面的Download(第一次访问需要点击Download下载驱动,后续就不再需要了),下载完成后再Test Connection,出现绿色的Succeeded就代表连接数据库成功。如果我们创建了两个ID都为1的user,那么也不会报错,因为我们仅仅只是在注释里说ID是唯一标识,但在数据库层面它是不知道这个是唯一标识的。

2026-02-03 11:15:52 638

原创 5-Web基础

服务器接收到这些请求后就需要对这些请求数据进行解析,而服务器要想能够成功解析出来所携带过来的请求,那它就要知道浏览器发送过来的请求数据到底长什么样子、具体的数据格式是什么样子的、具体每一项代表什么含义,否则无法解析。重定向:浏览器向服务器A发起请求,A发现浏览器请求的数据不在自己这里,在服务器B处,于是它会给浏览器返回一个3xx状态码,以及浏览器B的地址Location,浏览器获取到状态码与Location后,会向服务器B发起请求,进而得到数据。,请求到达服务器端后,服务器端接收这个请求并且读取数据。

2026-01-29 23:11:20 597 1

原创 4-初识Maven

Maven是一款用于管理和构建Java项目的工具,它基于项目对象模型(POM)的概念(把项目看成一个对象),通过一小段描述信息(pom.xml)来管理项目的构建。它提供了方便快捷的依赖管理(jar包)、标准化的跨平台的自动化项目构建方式、标准统一的项目结构。在以前我们想要导入jar包,要先到官网下载,然后再将其拷贝到我们的项目中,再将其移入到lib文件夹下。而对于Maven,我们只需要描述我们需要导入的jar包的信息即可。配置好信息后Maven会自动帮我们下载这个jar包。

2026-01-24 00:15:50 886

原创 力扣hot100-283移动零(盲人拉屎)

一旦左指针所在的位置为非零元素,左指针就要往后移动一位,否则就是占着茅坑不拉屎:因为左指针的用处本来就是标记下一个非零元素应该放到哪里,现在它的位置已经被占了,就应该往后挪。之所以是从left开始,不是left+1或left-1,是因为left本来就是标记下一个非零元素应该扔到哪里,而最后非零元素一定都被扔到left前面了,所以left开始后面的茅坑必须不能被屎填满。粗俗地说,右指针是一位盲人,非零元素好比右指针拉的屎,左指针是它的导盲犬,它告诉右指针应该往哪里拉屎。输出: [1,3,12,0,0]

2026-01-22 20:45:40 311

原创 3-Vue&Ajax

Vue是一款用于构建用户界面的渐进式的JavaScript框架。前端负责将数据以美观的样式呈现出来,而数据最终又要在数据库服务器中存储并管理。前端想要拿到数据,就需要请求服务器。然后服务器将数据返回给前端。Vue可以将这些原始的数据渲染展示在页面中,转换为用户可以看懂的网页,这就是构建用户界面,即基于数据渲染出用户看到的界面。准备工作:1.引入Vue模块2.创建Vue程序的应用实例,控制视图的元素3.准备元素(div),被Vue控制数据驱动视图:1.准备数据2.通过插值表达式渲染页面。

2026-01-22 20:20:40 646

原创 2-初识JS

JavaScript是一门跨平台、面向对象的脚本语言(即不需要编译就能直接运行),它用来控制网页行为,实现页面的交互效果。组成:ECMAScript:规定了JS基础语法核心知识,包括变量、数据类型、流程控制、函数、对象等。BOM:浏览器对象模型,用于操作浏览器本身,如页面弹窗、地址栏操作、关闭窗口等。DOM:文档对象模型,用于操作HTML文档,如:改变标签内的内容、改变标签内字体样式等。let 对象名 {属性名1: 属性值1;属性名2: 属性值2;...

2026-01-21 20:49:12 982

原创 Java动态代理

System.out.println("吃饭")现在我们想给eat方法增加一些东西,让吃饭这个动作更加完整System.out.println("拿筷子");System.out.println("盛饭");System.out.println("吃饭");这种修改叫做侵入式修改。在一个成熟的项目中,我们很少会这么修改,容易引发一系列连锁问题。那么问题来了,我现在不能修改原有的代码,又要增加额外的功能,该如何实现?

2026-01-13 18:20:52 277

原创 Java反射1

1.编写.java文件,并将其编译为.class字节码文件。在这个阶段代码没有被加载到内存中,只是在硬盘上进行操作。这个阶段是加载阶段。这三种方式对应Java当中三个不同的阶段。getDeclaredMethods则不能获取父类的,但可以获取私有的(和前面一样)invoke第一个参数表示方法的调用者,第二个参数表示在调用方法的时候传递的实际参数。3.我们可以在内存中new一个对象,这个阶段是运行阶段。1.getMethods方法可以获取所有public的方法对象,Class类中用于获取成员变量的方法。

2026-01-12 23:56:25 252

原创 NET1(Java中的网络编程、TCP的三次握手与四次挥手)

我们来分析一下在网络阻塞/客户端宕机情形下可能出现的一种情况:如果是两次握手:客户端发送SYN报文(seq=200),但这个SYN报文被网络阻塞了。接着客户端重新发送新的SYN报文(seq=100)。但旧的SYN报文比新的SYN报文先到达。服务端收到SYN报文后,进入ESTABLISHED状态,返回一个SYN-ACK报文(seq=400,ack=201),客户端发现ack应当为101,判断为历史连接,那么客户端发送RST报文断开连接。一段时间后,新的SYN报文才到达,这次才能正确握手。

2026-01-11 23:57:23 927

原创 JUC5(线程池)

核心元素:核心线程数量(非负)、线程池中最大线程数量(大于等于核心线程数量)、空闲时间(值)(非负)、空闲时间(单位)(用TimeUnit指定)、阻塞队列(非null)、创建线程的方式(非null)、执行任务过多时的解决方案(非null)。任务拒绝策略说明默认策略:丢弃任务并抛出RejectedExecutionException异常丢弃任务,但是不抛出异常,不推荐抛弃队列中等待最久的任务,然后把当前任务加入队列中调用任务的run()方法,绕过线程池直接执行3,//核心线程数量。

2026-01-10 18:28:28 548

原创 JUC4(生产者-消费者)

生产者做菜 消费者在吃,还能再吃9碗 生产者做菜 消费者在吃,还能再吃8碗 生产者做菜 消费者在吃,还能再吃7碗 生产者做菜 消费者在吃,还能再吃6碗 生产者做菜 消费者在吃,还能再吃5碗 生产者做菜 消费者在吃,还能再吃4碗 生产者做菜 消费者在吃,还能再吃3碗 生产者做菜 消费者在吃,还能再吃2碗 生产者做菜 消费者在吃,还能再吃1碗 生产者做菜 消费者在吃,还能再吃0碗。此时消费者还在wait,所以生产者要通知消费者开吃了(唤醒,notify),消费者被唤醒之后就开吃。队列,先进先出,不赘述。

2026-01-09 23:57:06 659

原创 JUC3(多线程中的安全问题)

分析一下原因:某个线程执行到了sleep,进入阻塞状态,此时另外某个线程拿到了执行权,但因为此时进入阻塞状态的线程还没释放锁,导致这个新拿到执行权的线程无法获得锁。另外,当ticket为100时,会跳过unlock直接break,它自己都死了还不舍得解开锁,这就导致了其它线程一直停在获取锁的那一行,所以程序不会停止。超出范围的原因也同理,ticket刚刚自增完,还没走出if语句块,执行权就被其它线程抢走了,其它线程也执行ticket自增,于是导致它们都还没走出if语句块,ticket就已经超出了范围。

2026-01-09 12:57:11 585

原创 JUC2(多线程中常用的成员方法)

例如非守护线程是打印1-10,守护线程是打印1-100.当非守护线程执行完后(注意,不是等到非守护线程执行完了,守护线程才开始执行),守护线程会被告知可以结束了,只不过在这个被告知的过程中守护线程自己也运行了。简单地说,当巨人线程打印了之后,由于CPU执行权还在巨人线程,它可能会一下子打印很多个数字,直到CPU执行权被矮人线程抢走。在Java中,线程的优先级最小是1,最大是10,默认是中间的5. 线程优先级越大,抢占到CPU的概率越高。线程有默认的名字,格式为:Thread-X(X为序号,从0开始)。

2026-01-08 23:42:05 490

原创 JUC1(多线程的三种实现方式)

点击顶部菜单 文件 -> 项目结构(或快捷键Ctrl+Alt+Shift+S) -> 项目 -> 语言级别 -> 选择与你本地JDK版本匹配的项目语言级别。在左侧找到模块 -> 右侧切换到路径 -> 点击 使用模块编译输出路径 -> 选择输出目录 -> 测试输出目录可以选择同一个目录。每个模块有独立的编译目录,多模块项目中便于区分不同模块的编译产物,结构更清晰。没有指定输出路径,那么IDEA就不知道把编译后的class文件放到哪里,所以我们要给模块配置输出目录。方法一的可扩展性较差,不能再继承其它的类。

2026-01-07 22:51:24 262

原创 IO流7(打印流、压缩与解压缩流)

相当于获取了一个打印流,它被称作是系统中的标准输出流,该流是不能关闭的,因为它在系统中是唯一的,除非我们重启JVM。这个打印流是Java启动后由虚拟机自己创建的,不需要我们手动创建。1.在项目中创建一个文件夹lib,用于存放第三方的jar包(第三方组织将写好的代码打包成一个压缩包,在Java中压缩包的后缀为jar)例如打印97,写到文件中的就是97,而不是其对应的ASCII码a。Ctrl+ B可以看到,System是一个类,而out是类的一个。需要说明的是,压缩包里的每一个文件,在Java中都是一个。

2026-01-07 14:01:36 643

原创 IO流(转换流、序列化与反序列化流)

如果我们不想把一些变量序列化到本地文件,我们可以为它加上transient关键字(瞬态关键字),它的作用就是不会把当前属性序列化到本地文件中。由于字节流在读中文的时候会出现乱码,并且字节流中没有读一整行的方法,因此要考虑先将字节流转换为字符流,再将字符流包装成字符缓冲流。因为在数据的目的地,也就是文件中,它真实的存储形式就是一个又一个的字节。但需要注意的是,不要一上来就生成版本号,因为这个版本号是根据类的内容计算出来的。反序列化流(又名对象操作输入流)可以把序列化到本地文件中的对象读取到程序中。

2026-01-06 17:55:26 689

原创 IO流5(缓冲流)

对于字节数组来说,缓冲区确实是8KB,因为是byte类型的。但对于字符数组,它是char类型的,其缓冲区能容纳8192个字符,而1个字符占2个字节,所以字符缓冲流底层的缓冲区大小是16KB. 准确的说法是:缓冲流自带长度为8192的缓冲区。创建字节缓冲输入流与字节缓冲输出流对象后,硬盘(数据源)与内存之间就建立了两条通路,并且在内存中建立了两个缓冲区,一个是字节缓冲输入流的,另一个是字节缓冲输出流的。关于”包装“,实际上缓冲流是不能读写数据的,我们只不过是将它与读写流关联起来,真正干活的还是读写流。

2026-01-05 21:17:58 680

原创 IO流4(小练习)

对图片a进行加密,就是将它的每个字节与128进行异或,改变它,得到不可打开的图片b. 想要解密时,就将图片b“拷贝”到图片c,只不过拷贝的过程中,将每个字节都与128进行异或,相当于图片a的每个字节先后与128进行异或,回到它本身,实现了解密。表示的并不是”长度“,而是数组的元素个数,所以其值为6.这也是好理解的,因为数组的元素是Integer类的,所以自然不会算上分隔符以及头尾的中括号。将文本文件中的“2-1-9-4-7-8”排序,即修改为“1-2-4-7-8-9”,用于存放拷贝过来的文件。

2026-01-05 00:06:52 690

原创 IO流3(字符流)

如果没有,就先从文件中尽可能多地将数据读入缓冲区(尽可能多,指的是能塞满缓冲区就塞满),然后再从缓冲区中读数据。第一次调用read方法,此时缓冲区为空,会先从文件中读取数据到缓冲区,因为一个中文汉字是3个字节,所以会读取4个字节到缓冲区。接着,从缓冲区中读数据,读到的是第一个字节,把第一个字节按照UTF-8规则进行解码,转换为十进制,赋值给。我们发现输出的是一串数字。第三次调用read方法,此时缓冲区为空,那么它就会从文件中尽可能多地将数据读入缓冲区,但是此时文件已经到末尾了,所以会返回-1,并赋值给。

2026-01-04 19:57:00 610

原创 IO流2(捕获异常、乱码与字符集)

但是它的编码规则比较不同。不过,如果是3个字节,最高位字节前面要加1110,次高位与最低为字节前面要加10.如果是2个字节,最高位前面补110,最低位前面补10.如果是4个字节,最高位前面补11110,其它字节前面补10.其余的比特位用实际查询到的数字填充即可。假设我们现在存储字母a,它对应的ASCII码是97,对应的二进制是110 0001,但由于字节是计算机中最小的存储单元,97只有7位,不足8位,所以需要编码,将字符集中查询到的数据按照一定的规则进行计算变成真实的、实际能存储在硬盘中的二进制数据。

2026-01-03 23:47:15 494

原创 JavaIO流1

IO流用于读写文件中的数据,或者网络中的数据。谁在读?谁在写?是程序在进行读写。或者说内存进行读写,因为程序是运行在内存中的。

2026-01-01 14:20:35 662

原创 Java中的文件操作

/获取内容,看后缀。

2025-12-11 15:31:34 724

原创 JavaTreeMap源码分析

创建一个Entry对象表示待添加的节点,然后根据cmp的大小决定它应该放父节点的左边还是右边,并建立连接。通过这四个函数,可以获得x的叔叔节点:leftOf(parentOf(parentOf(x)))或者rightOf(parentOf(parentOf(x)))cmp是两个元素的键比较之后的结果,负数表示当前要添加的元素较小,放在左子树。如果t为null,表示当前是第一次添加,创建根节点,返回null,表示没有覆盖任何元素。新建一个名为parent的Entry对象,表示要添加的节点的父节点。

2025-12-02 00:28:30 650

原创 JavaHashMap源码分析

e(对象C的地址)的哈希值也不等于D1的哈希值,不会进入if中,最后将e赋值给p,也就是原本为对象A的p,现在变成了对象C,这实际上相当于双指针迭代遍历链表。由于键不一样,那么由于A后面还有一个对象C,C后面还有D,再比较,发现键的哈希值相同,就要进行覆盖操作。为true,那么就进入if语句,将待加入的节点的value赋值给待覆盖节点的value,再返回待覆盖节点原本的value。,值为333的对象C加入HashMap中,恰好算出来的应该存入哈希表中的位置就是下标为2的位置,发生重复。

2025-12-01 17:40:11 689

原创 160相交链表

假设遍历A链表的指针名为a,遍历B链表的指针名为b:那么我们只需要让a和b先遍历完链表,如果遇到最后一个节点,就跳回到对方链表的开头即可,相当于走一遍对方走过的路程,这样只要链表有相交的地方,就必然会在相交的位置相遇。输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。

2025-11-26 11:48:28 857

原创 1两数之和

我们可以通过哈希表,遍历x的时候,查找哈希表中是否存在target-x即可。也就是说,我们不能向后看,因为还没有遍历到,但是可以回头看,看x左侧是否存在target-x。在遍历到x时,从x后面开始寻找target-x,之所以要从后面找,是因为x前面的元素必然已经和x匹配过。解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]。输入:nums = [2,7,11,15], target = 9。输入:nums = [3,2,4], target = 6。,请你在该数组中找出。

2025-11-25 09:18:26 318

原创 WebServer06

而参数需要的是裸指针,且对象还是自动管理的,局部智能指针超出作用域后还是会自动delete对象。可见,release()是永久交出对象控制权,让对象脱离智能指针管理。重复执行大括号里的内容100次,相当于你手动打开了100个终端,每个终端都执行一次连接服务器+发数据的操作。每个循环末尾的&:让这个连接在后台运行,不阻塞下一个连接的创建,这使得100个连接瞬间同时建立,而不是排队。如果不是,就看该事件关心的是读事件还是写事件,分别进行处理即可。是线程不安全的,因为它使用的是静态缓冲区,多线程调用会覆盖结果。

2025-11-18 21:03:28 630

原创 设置共享文件夹

在Windows主机中创建文件夹SharedFolder,作为共享文件夹。并在VMWare界面上方的”虚拟机“ -> ”设置“ -> "选项"中找到共享文件夹,填入这个SharedFolder的路径,选择总是启用。如果你前面没有设置uid和gid,在这里正常写入uid和gid即可。文件夹与主机中的SharedFolder文件夹就是互通的了。如果什么都没有输出,那说明配置无错误。

2025-11-14 23:58:12 274

原创 WebServer05

符号,这是因为新开的客户端与服务端完成三次握手后放入了已完成连接队列中,但accept没有放在循环里,因此服务端只会从已完成连接队列中取出一次连接,后面即使有新的连接也取不出来了。客户端回复ACK,三次握手完成,内核将这个全连接从未完成队列移动到已完成连接队列,此时连接已就绪,等待服务端处理。如果我们再开一个终端,运行client,是可以与服务端建立连接的,但是服务端却没有显示IP客户端的IP地址,新开的客户端向服务端发送消息,服务端也接收不到。这就是arg存在的意义。的已完成连接队列中取一个就绪的连接。

2025-11-12 16:56:49 970

原创 WebServer04

它的核心优势在于:跨平台(同一个CMakeLists.txt,在Linux生成Makefile,在Mac OS生成XCode工程,在Windows生成VisualStudio工程)、简化配置(自动找源文件、自动处理依赖)、支持复杂项目(处理多目录、动态/静态库、第三方依赖)而且不同的人可能使用不同的编译选项。前者:你写的会多一点,但你看试卷复习的时候就不需要翻阅课本了。链接过程:编译器不会复制库的代码,只会在你的可执行文件中记录 “我需要用到 xxx 动态库的 xxx 函数”,相当于留了一个引用地址。

2025-11-11 23:57:22 921

原创 力扣146LRU缓存

找到对应节点之后要将其移动到最前面,那这就意味着我们需要知道第二个节点的指针,这有点麻烦,因为第二个节点可能会变化。并且,每个节点要存储key/value/next/prev,因为找到尾节点之后还要返回它的key值,这样才能从哈希表中删除。但是问题又来了:如果我们把中间的元素移到了上面,那空出来的位置要补上,这就意味着必然要进行移动操作,那时间复杂度肯定不是O(n)了。因为在链表中删除元素是O(1)操作,不涉及补位,也没有预分配空间的问题。// 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}

2025-11-04 11:05:19 1008

原创 上传项目至Github与从Github克隆项目

生成token:点击头像 -> Settings -> Developer Settings -> Personal access tokens -> Tokens(classic) -> Generate new token -> Generate new token(classic)推送时要求我们输入账号密码,但现在Github使用的是personal access token而不是账号密码。然后把你需要上传的文件移动/复制到这个克隆下来的文件夹里,cmd中使用copy或remove。

2025-10-31 15:22:17 415

原创 select/poll/epoll

epoll_wait。

2025-10-29 23:52:08 1102

原创 WebServer 03

我们回到WebServer,继续看Config类中的parse_arg函数(命令行参数解析器)。我们先理解一下这个getopt函数做了什么。getopt函数是Linux/Unix系统中用来解析命令行参数的标准库函数。argc和argv就不再赘述了,在01中学习过。opstring的格式规则:单个字母表示选项,后面跟冒号表示需要参数"abc" //-a,-b,-c选项都不需要参数"a:b:c:" //-a,-b,-c选项都需要参数"ab:c" //-a和-c不需要参数。

2025-10-21 00:27:10 865

原创 437路径总和III(dfs+前缀和)

当我们搜索到节点node时,计算出其前缀和为curr,我们希望在根节点root到node之间,存在这么一个节点node1,使得node1到node的和为target,那么这就意味着node1的前缀和为curr-target.为了记录数量,我们使用哈希表。输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22。输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8。

2025-10-17 23:33:39 419

原创 2333贪心

从最后一个元素开始,change=1,因此消耗1个单位,让差值为3的那个对子变成差值为2,因此gap[2]要加一,gap[3]要减一,k也要减一。输入:nums1 = [1,2,3,4], nums2 = [2,10,20,19], k1 = 0, k2 = 0。输入:nums1 = [1,4,10,12], nums2 = [5,8,6,9], k1 = 1, k2 = 1。解释:假设差值分别为[1,2,2,3]且k=4,那么gap[1]=1,gap[2]=2,gap[3]=1.

2025-10-15 10:07:12 374

原创 反转链表及其应用(力扣2130)

是因为每一个对子(prev,curr)的函数都返回的是下一个对子(curr,tmp)的函数的返回值,也就是说,func(A,B)返回值依赖func(B,C),func(B,C)返回值依赖func(C,D),最终的返回值就是func(D,nullptr),也就是新链表的头节点。对于A->B->C来说,调整为A<-B->C后,需要记录C,不然就不知道哪个节点要指向B了。找到待反转部分最左侧节点的前一个节点和最右侧节点的后一个节点,再把待反转部分单独抽出来,回到上一个问题,再调整指针指向即可。

2025-10-13 21:20:57 845

原创 WebServer 02

我们来分析一下在网络阻塞/客户端宕机情形下可能出现的一种情况:如果是两次握手:客户端发送SYN报文(seq=200),但这个SYN报文被网络阻塞了。接着客户端重新发送新的SYN报文(seq=100)。但旧的SYN报文比新的SYN报文先到达。服务端收到SYN报文后,进入ESTABLISHED状态,返回一个SYN-ACK报文(seq=400,ack=201),客户端发现ack应当为101,判断为历史连接,那么客户端发送RST报文断开连接。一段时间后,新的SYN报文才到达,这次才能正确握手。

2025-10-12 12:37:10 582

.arch7章标准件习题-Model.pdf

.arch7章标准件习题-Model.pdf

2024-11-21

ad2d87c9c1743df621c5b05971f1de49.zip

ad2d87c9c1743df621c5b05971f1de49.zip

2024-10-24

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除