自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Redis 篇-深入了解 Redis 中的 RESP 通信协议与内存回收(过期 key 处理、内存淘汰策略)

删除完之后,再判断内存是否充足,如果还是不足,那么会接着循环来删除 key,如果达到充足的内存,则直接退出删除 key 的操作。若选择的删除策略为:TTL、LRU、LFU 这些策略,先创建一个池,用来存放准备删除的 key,在 Redis 数据库中从 0 直到 15 的数据库进行遍历抽样选择要放入池中的 key,默认每次抽样 5 个 key。如果当前内存不充足时,继续判断内存策略是否为默认 noeviction 策略,也就是即使内存满了,也不会执行删除 key 的操作,会发出错误信息。

2024-09-29 10:19:24 1769 91

原创 Redis 篇-深入了解在 Linux 的 Redis 网络模型结构及其流程(阻塞 IO、非阻塞 IO、IO 多路复用、异步 IO、信号驱动 IO)

1)抛开持久化不谈,Redis 是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。2)多线程会导致过多的上下文切换,带来不必要的开销。3)引入多线程会面临线程安全问题,必然要引入线程锁这样的安全手段,实现复杂度增高,而且性能也会大打折扣。

2024-09-26 16:28:09 1885 91

原创 Redis 篇-深入了解 Redis 五种数据类型和底层数据结构(SDS、Intset、Dict、ZipList、SkipList、QuickList)

每次执行新增、查询、修改、删除操作时,都检查一下 dict.rehashidx 是否大于 -1,如果是则将 dict.ht[0].table[rehashidx] 的 entry 链表 rehash 到 dict.ht[1],并且将 rehashidx++。:如果当前层已经达到目标值或找到了更大的值,改变层级,将 current 指针向下移动到下一层。5)将 dict.ht[1] 赋值给 dict.ht[0],给 dict.ht[1] 初始化为空哈希表,释放原来的 dict.ht[0] 的内存。

2024-09-24 15:55:26 1478 68

原创 Redis 篇-初步了解 Redis 持久化、Redis 主从集群、Redis 哨兵集群、Redis 分片集群

在子进程写入磁盘过程中,主进程有可能会进行写操作,所有为了防止脏读的情况,在写数据的时候,将内存的数据进行拷贝,再来进行写操作。在 slave 加载 RDB 文件的时候,master 也会不断接收写操作的请求命令,这些命令会先保存到 repl_baklog 文件中,等待 slave 加载完成之后,master 发送 repl_baklog 中的命令到 slave 节点中,而 slave 节点接收到命令就会执行。重新启动该 Redis 服务之后,会自动从 RDB 文件中获取数据,重新将数据放到内存中。

2024-09-17 20:49:07 1698 84

原创 Redis 篇-深入了解使用 Redis 中的 GEO 数据结构实现查询附近店铺、BitMap 实现签到功能、HyperLogLog 实现 UV 流量统计

GEO 就是 Geolocation 的简写形式,代表地理坐标。Redis 在 3.2 版本中加入了对 GEO 的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据。

2024-09-14 10:22:44 1522 65

原创 Redis 篇- 实战项目中使用 Redis 实现经典功能(异步秒杀商品、点赞功能、共同关注的好友、投喂功能)

查看消息的时候,按照时间来查看,从最新的时间到最旧的时间的顺序来进行查看,比如说,朋友圈,打开朋友圈最先看到的是最新的好友信息,用户查询自己的收件箱,比如像朋友圈,按照时间来排序好友发布的信息,而查看好友的朋友圈的时候,从上至下,来查看好友的消息。从用户集合中查询信息也不难,在实现的时候不就是直接去查看当前用户的收件箱,其实不然,需要考虑的细节还挺多的。

2024-09-11 22:29:47 2148 56

原创 Redis 篇-深入了解基于 Redis 实现消息队列(比较基于 List 实现消息队列、基于 PubSub 发布订阅模型之间的区别)

key 为队列名称,*|ID 为消息的唯一 id,* 代表由 Redis 自动生成。group 代表组名,consumer 代表组内消费者名称,count 代表每次读取的最大数量,milliseconds 代表当没有消息时最长的等待时间,NOACK 代表无需手动 ACK,获取消息后自动确认。当使用 Stream 单消费者模式的时候,我们指定起始 ID 为 $ 时,代表读取最新的消息,如果我们处理一条消息的过程中,又有超过 1 条以上的消息到达队列,则下次获取时也只能获取到最新的一条,会出现漏读消息的问题。

2024-09-10 10:14:04 1694 51

原创 Redis 篇-深入了解分布式锁 Redisson 原理(可重入原理、可重试原理、主从一致性原理、解决超时锁失效)

Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网络。它不仅提供了一系列的分布式的 Java 常用对象,还提供了许多分布式服务,其中包含了各种分布式锁的实现。Redisson 解决了不可重入问题、不可重试问题、超时释放问题、主从一致性问题。比如说,分布式锁的可重入锁、公平锁、联锁、红锁等等。

2024-09-08 21:36:17 2546 50

原创 Redis 篇-深入了解基于 Redis 实现分布式锁(解决多线程安全问题、锁误删问题和确保锁的原子性问题)

假设线程一正常获取锁之后,执行任务,但是该任务出现了阻塞情况,等待的时间较久,此时当锁到过期时间之后,就会自动被释放了,当时此时线程一还不知道当前锁被释放了,就在这时候,线程二来正常的获取锁,因为锁已经被释放了,所以线程二是可以获取锁成功的,接着,线程二获取锁之后,就开始执行任务了,此刻线程一任务执行完之后,会直接释放锁,这就出现线程一误删了线程二的锁问题。为了解决 Redis 分布式锁被误删的问题,可以想到的办法是:在释放锁之前,判断当前的锁 “是否” 是自己之前获取的锁,如果是,则可以直接释放锁;

2024-09-07 18:03:03 1867 36

原创 Redis 篇-深入了解查询缓存与缓存所带来的问题(读写不一致、缓存穿透、缓存雪崩、缓存击穿)

如果没有命中,根据用户 id 到数据库中查询用户信息,如果用户信息不为 null ,则说明用户信息是存在的,那么将用户信息写回到缓存中,方便下一次查询可以直接从缓存中获取用户信息;第一次会到数据库查询该用户信息,当该用户信息不存在时,则会在 redis 中设置空值,这样的好处,下一次的查询该用户,就不会打到数据库中了,减少了数据库的压力。设置缓存中 key 的逻辑过期,顾名思义:在实际上,缓存中的 key 是设置永远不过期,将其添加过期字段,通过查看该字段,来判断该 key 在缓存中是否已经过期了。

2024-09-03 10:30:36 2359 63

原创 SpringBootWeb 篇-深入了解 SpringBoot + Vue 的前后端分离项目部署上线与 Nginx 配置文件结构

它的主要用于在 windows 平台上远程连接管理 Linux 系统,用户可以通过 Xshell 连接到远程服务器,执行命令、管理系统、进行系统监控等操作。Xshell 连接云服务器的步骤:1)点击新建:2)先起一个好听的名字,再将公网 IP 填写到主机(H),再按确认3)双击新建好的会话,之后就会自动弹出来 SSH 用户名卡片的填写,这里用到了连接云服务器的登录名信息。4)继续双击会话,之后会弹出用户身份验证,这里用到了连接云服务器的密码信息。5)最后出现了绿点和一串复杂的字符串。

2024-08-22 11:31:20 10008 64

原创 SpringBootWeb 篇-入门了解 Swagger 的具体使用

其中设置 apis(RequestHandlerSelectors.basePackage("需要扫描的项目名")) 该属性是很重要的,项目中要测试的方法或者类在具体包的包名。简单来说,通过这些注解就可以对类、方法、方法中的属性进行说明,在测试方法的过程中,可以很清晰的明白该方法或者类的用途、信息。4)@ApiOperation("对方法进行描述"):用在方法上,例如 Controller 的方法,说明方法的用途、作用。2)Swagger 在开发阶段使用的框架,帮助后端开发人员的接口测试。

2024-07-12 17:08:31 7404 66

原创 SpringBootWeb 篇-入门了解 Vue 前端工程的创建与基本使用

axiox.post(url[,data[,config]]):url 表示请求路径,config 表示配置对象,可以设置查询参数、请求头信息,data 表示请求体数据,最常见的是 JSON 格式数据。绑定发送 get 请求的方法,先获取到 token 字段的值,再将 token 字段的值设置为发送 get 的请求的请求头 token 的字段值。绑定了一个发送请求的方法,使用 axiox.post() 方法来发送 post 类型的请求给后端,执行成功后,会自动调用 then() 方法。

2024-06-20 19:38:26 5552 75

原创 SpringBootWeb 篇-入门了解 Apache POI 使用方法

简单来说就是,开源使用 POI 在 Java 程序中对 Miscrosoft Office 各种文件进行读写操作。首先需要添加 POI 库的依赖,在前面写入 Excel 文件中已经添加了,这里就没有必要继续添加依赖了。通过 new File("路径") Flie 对象作为参数来指定要读取的 Excel 文件。使用 XSSFWorkbook 创建 XLSX 格式的 Excel 文件。一般情况下, POI 都是用于操作 Excel 文件。根据索引或者名字来获取指定的 Sheet 对象。

2024-06-17 21:29:29 2830 64

原创 SpringBootWeb 篇-入门了解 Spring Cache 、Spring Task 与 WebSocket 框架

当请求发送到服务端,先根据 (cacheNames = "user",key = "#id") 查询 Redis 缓存是否存在相应的数据,当前是第一次查询,因此缓存不存在相应的数据,所以会到数据库中查询数据,查询之后,会将结果自动放入到 Redis 缓存中,那么下一次查询相同的数据,就会直接从 Redis 缓存中获取到。Spring Cache 通过将方法调用的结果缓存在缓存中,下次再次调用该方法时,直接从缓存中取数据,避免了重复计算,减少了系统的负担和资源消耗。

2024-06-16 12:11:01 4239 57

原创 SpringBootWeb 篇-深入了解 Redis 五种类型命令与如何在 Java 中操作 Redis

redis.windows.conf:配置文件,用来配置 Redis 服务器的各种参数和选项。redis-server.exe:Redis 服务端可执行文件,用来启动 Redis 服务端。redis-cli.exe:Redis 客户端可执行文件,用来启动 Redis 客户端。

2024-06-10 10:29:07 15321 98

原创 SpringBootWeb 篇-深入了解 AOP 面向切面编程与 AOP 记录操作日志案例

AOP,Aspect Oriented Programming 面向切面编程,在 AOP 中,横切关注点被称为切面(Aspect),切面通过特定的注入方式被应用到程序的不同部分,从而实现对这些部分的增强或修改。AOP 能够帮助开发者更好地管理程序的复杂性,提高代码的重用性和易读性。简单来说,就是面向特定的方法编程,也或者说给原始的方法进行升级改造。这样原始的方法就不需要进行改变,从而实现方法升级了。如日志记录、权限控制等功能。通过AOP,可以实现方法的升级改造,提高代码的可维护性和可重用性。

2024-06-07 09:24:27 3123 68

原创 SpringBootWeb 篇-深入了解 Bean 的管理与 SpringBoot 起步依赖、SpringBoot 自动配置原理(源码追踪:jar 包配置类如何加载到 IOC 容器中?)

如果配置类中使用了 @Configuration 注解,并且在配置类中定义了 @Bean 注解的方法用于创建 bean 对象,这些 bean 对象也会被加载到 Spring 的 IOC 容器中。一般通过常见的基于注解的配置方式来完成 Bean 的管理。如果使用 @Import 导入的类是一个带有 @Configuration 注解的配置类,Spring 会将该配置类作为一个配置文件加载,其中定义的 @Bean 方法将被调用以创建 bean,并将这些 bean 加载到 IOC 容器中。

2024-06-04 21:06:21 3203 79

原创 SpringBootWeb 篇-深入了解 Spring 异常处理、事务管理和配置文件参数配置化、yml 配置文件

首先创建一个捕获异常的类,在类中定义一个方法且在该方法上加上 @ExceptionHandler 注解,在注解上设置 Exception.class 的属性,从而捕获全局的异常。Propagation.REQUIRES_NEW:创建一个新的事务,并暂停当前事务(如果存在)。新事务和当前事务之间是独立的,互不影响。Propagation.REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是最常用的传播行为。

2024-06-01 17:24:15 2224 42

原创 SpringBootWeb 篇-深入了解 Filter 过滤器与 Interceptor 拦截器(实现登录校验 Filter + Interceptor + JWT 令牌)

Filter 过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。过滤器可以把资源的请求拦截下来,从而实现一些特殊的功能。过滤器一般完成一些通用的操作。比如:登录校验,统一编码处理、敏感字符处理。是一种动态拦截方法调用的机制,类似于过滤器。Sring 框架中提供的,用来动态拦截控制器方法的执行。在拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。

2024-06-01 17:15:48 3651 85

原创 SpringBootWeb 篇-深入了解会话技术与会话跟踪三种技术(Cookie 会话跟踪、Session 会话跟踪与 JWT 令牌会话跟踪)

三种会话技术:Cookie、Session、JWT 令牌技术,生成 JWT 与校验 JWT 代码实现。一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求间共享数据。用户打开浏览器,访问 web 服务器的资源,会话建立,直到有一方断开,会话结束。在一次会话中可以包含多次请求和响应。

2024-05-29 22:27:34 4084 82

原创 SpringBootWeb 篇-深入了解 Mybatis 中的 XML 映射文件、Mybatisx 插件与动态 SQL(if、foreach、sql & include 等)

MyBatisX 插件提供了可视化的操作界面,可以通过简单的操作就能生成相应的代码模板,支持根据数据库表结构生成代码,自定义生成策略,以及生成代码后自动格式化等功能。在 MyBatis 中根据不同条件动态生成 SQL 语句的技术。通过使用动态 SQL,可以根据不同的情况生成不同的 SQL 语句,以满足各种查询条件下的需求,从而提高 SQL 语句的灵活性和可重用性。动态 SQL 中的 foreach 标签用来迭代集合中的元素,并把每个元素作为参数传入 SQL 语句中,实现对集合中所有元素进行相同操作的功能。

2024-05-25 19:14:42 1606 72

原创 SpringBootWeb 篇-深入了解 Mybatis 删除、新增、更新、查询的基础操作与 SQL 预编译解决 SQL 注入问题

SQL 预编译是在执行 SQL 语句之前,将 SQL 语句编译成可执行的硬编码形式,并在执行时直接使用编译好的代码,从而减少了每次执行 SQL 语句时的语法解析和优化等过程,提高了 SQL 语句执行的效率。注意事项:#{} 占位符不能内嵌在 "" 中,而 ${} 占位符可以内嵌在 "" 中。在数据添加成功后,需要获取插入数据库数据的主键。2)更安全(防止 SQL 注入)concat() 方法。

2024-05-24 12:22:58 1512 59

原创 SpringBootWeb 篇-深入了解 Mybatis 概念、数据库连接池、环境配置和 Lombok 工具包

数据库连接管理:JDBC 需要手动管理数据库连接的打开和关闭,而 MyBatis 可以通过配置文件自动管理数据库连接的打开和关闭,减少了开发人员的工作量。4)连接超时处理:数据库连接池可以设置连接的超时时间,当连接空闲时间超过设定的时间时,连接将被释放,避免连接过期或长时间占用的情况发生。需要注意的是,这里的密码和数据库名都是自定义的,不是完全相同的,要依据你当前要操作的数据库名和你当前的数据库密码。1)资源重用:数据库连接池可以重用已经创建的数据库连接,减少了连接的创建和销毁开销,提高了系统的性能。

2024-05-21 19:30:27 2975 76

原创 SpringBootWeb 篇-深入了解分层解耦与 IOC&DI(通过实现案例来讲解)

在 SpringBootWeb 开发中,分层解耦是一种常见的设计原则,用于将应用程序的不同功能模块分成不同的层次,每个层次负责不同的功能,从而实现代码的可维护性、可扩展性和可测试性。常见的分层结构包括控制器层服务层持久层等。在讲解 IOC&DI 之前,先来讲解一下内聚和耦合。

2024-05-16 16:47:17 1991 76

原创 JavaEE 初阶篇-深入了解网络原理 TCP/IP 协议

TCP 协议在传输层,TCP 是传输层协议的一种,传输层中的协议不单单只有 TCP 或者 UDP。当应用层将数据打包后交给传输层时,如果选择使用 TCP 协议,传输层会在数据包上加上 TCP 报头;如果选择使用 UDP 协议,传输层会在数据包上加上 UDP 报头。1)MSL 是 TCP 报文的最大生存时间,因此 TIME_WAIT 持续存在 2 MSL 的话,就能保证在两个传输方向上的尚未接收或者迟到的报文都已经消息。

2024-05-14 21:13:05 1499 64

原创 SpringBootWeb 篇-深入了解请求响应(服务端接收不同类型的请求参数的方式)

当客户端发送不同的请求参数到服务端,服务端就需要进行不同的方法方式来接收请求参数。一般的请求参数的类型包括:简单参数、实体参数、数组集合参数、日期参数、json 参数、路径参数。 客户端无论通过 get 或者是 post 方式来发送请求,对应发送简单请求参数来说,是通过键值对的方式来发送到服务端。方法一:服务端可以用到 HttpServletRequest 类对象来接收简单参数请求,再通过对象名.getParam("请求参数名") 方法来获取值。

2024-05-11 16:29:12 3884 100

原创 JavaEE 初阶篇-深入了解 HTTP 协议

请求头:包含一系列的键值对,用于传递请求的元数据信息,如 User-Agent(用户代理)、Host(主机名)、Content-Type(内容类型)等。请求由请求行、请求头和请求体组成,响应由状态行、响应头和响应体组成。接着,服务端接收到来自客户端发送的请求,先验证发送的请求行是否正确,接着响应客户端请求的数据。状态行包含了响应的状态码和描述,响应头包含了响应的元数据信息,空行用于分隔响应头和响应体,响应体包含了实际的响应数据。1)请求行:包含请求方法、请求的 URL 和协议版本。

2024-05-09 14:49:37 1646 78

原创 JavaEE 初阶篇-深入了解 Junit 单元测试框架和 Java 中的反射机制(使用反射做一个简易版框架)

可以用来对方法进行测试,它是第三方公司开源出来的(很多开发工具已经集成了 Junit 框架,比如 IDEA)优点:1)可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立。2)不需要程序员去分析测试结果,会自动生成测试报告出来。具体步骤:1)将 Junit 框架的 jar 包导入到项目中(注意:IDEA 集成了 Junit 框架,不需要我们手动导入)

2024-05-03 16:39:21 3890 106

原创 JavaEE 初阶篇-深入了解网络原理中传输层的端口号与 UDP 协议报文格式

如果一个进程绑定多个端口号,是否可行呢?除了 CRC 的算法还有 MD5 算法。如何确认在当前机器上,某个端口是否被其他进程使用了呢?在同一个机器上,同一个时刻内,端口号不能重复被绑定。UDP 数据报 = UDP 报头 + UDP 载荷。3)两个进程不能绑定同一个端口号。

2024-05-01 11:55:40 2835 66

原创 JavaEE 初阶篇-深入了解特殊文件(Properties 属性文件、XML)

Properties 属性文件是Java中一种常见的配置文件,用于存储键值对。它通常以“.properties”为后缀,采用“key=value”的格式来存储数据,其中“key”表示属性名,而“value”表示属性值。XML 可扩展标记语言,是一种用于存储和传输数据的标记语言。XML 被设计用来传输和存储数据,同时具有自我描述性和可扩展性的特点。XML 的语法规则比较严格,它使用标签来标记数据,标签可以自定义,从而使 XML 具有很强的灵活性。

2024-04-29 17:24:55 2345 81

原创 JavaEE 初阶篇-深入了解 I/O 高级流(缓冲流、交换流、数据流和序列化流)

缓冲流(Buffered Stream)来提高 I/O 操作的效率,缓冲流是对字节流和字符流的一种封装,通过缓冲区来减少 I/O 操作的次数,从而提高程序的运行效率。简单来说,InputStreamReader 将读取的字节流转化为字符流,并且如果读取的是用 GBK 编码集进行编码的,在 UTF 环境下进行编码时,则需要指定用 GBK 编码集进行编码。序列化流是 Java I/O 中的一种特殊流,用于将对象转换为字节序列以便存储或传输,或将字节序列转换回对象。主要是为了,方便取数据而不是给程序员看的。

2024-04-26 20:12:30 2457 69

原创 JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊)

先创建 ServerSocket 类,用有参构造器 ServerSocket(int port) 创建指定端口号的对象,再用 accept() 方法来等待接收来自客户端发送来的连接请求,客户端与服务端连接完毕之后,就会返回一个 Socket 对象给服务端,该 Socket 对象可以理解为管道的服务器的一端,客户端已经有 Socket 对象了,该对象就可以理解为管道的客户端的一端。用于创建客户端、服务端。由于 IP 的限制(IP 为内网),不能让其他的机器连接目前的机器,所以只能本机的程序连接本地的程序。

2024-04-25 15:34:53 2439 69

原创 JavaEE 初阶篇-深入了解网络通信相关的基本概念(三次握手建立连接、四次挥手断开连接)

第一次握手(SYN):客户端向服务器发送一个带有 SYN 标志的数据包,表示请求建立连接。此时客户端进入 SYN_SENT 状态。简单来说,第一次握手可以说明:客户端此时是否具备发消息的能力。第二次握手(SYN + ACK):服务器接收到客户端发送的 SYN 数据包后,向客户端发送一个带有 SYN 和 ACK 标志的数据包,表示确认收到请求,并同意建立连接。此时服务器进入 SYN_RECV 状态。简单来说,第二次握手可以说明:假设服务端收到了来自客

2024-04-24 15:06:06 1674 66

原创 JavaEE 初阶篇-深入了解 I/O 流(FileInputStream 与 FileOutputStream 、Reader 与 Writer)

如果文件已存在,会覆盖原有内容,也可以给构造器中再传入一个参数 true ,以支持继续追加,不会覆盖原有的内容。每次调用 read() 方法会读取一个字节,并返回读取的字节数据(以 int 类型表示,范围为 0 到 255),如果已到达文件末尾,则返回 -1。如果文件过大,创建的字节数组也会过大,可能引起内存溢出。字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。定义一个与文件一样大小的字节数组,一次性读取完文件的全部字节。使用字节流读取中文,如何保证输出不乱码,怎么解决?

2024-04-21 22:31:12 2157 95

原创 JavaEE 初阶篇-深入了解 File 文件操作(实现文件搜索、非空文件夹删除)

在 Java 中,File 类是用于表示文件和目录路径的类,它提供了一组方法来操作文件系统中的文件和目录。File 类位于 java.io 包中,是 Java 中处理文件和目录的基本类之一。文件是非常重要的存储方式,在计算机硬盘中,即便断电,或者程序终止了,存储在硬盘文件中的数据也不会丢失。通过 File 类可以创建文件对象,从而获取文件信息(大小,文件名,修改时间),判断文件的类型,删除文件/文件夹等等。重点要注意的是:File 类只能文件本身进行操作,不能读写文件里面存储的数据。

2024-04-21 18:26:49 1525 37

原创 Java 算法篇-深入了解 BF 与 KMP 算法

KMP 是一种高效的字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。KMP 算法的核心思想是利用已匹配的信息来尽量减少不必要的比较,从而提高匹配效率。KMP 算法的时间复杂度为 O(m+n),其中 m 是主串的长度,n 是模式串的长度。相比于 BF 暴力匹配算法,KMP 算法具有更高的效率,尤其在处理大规模文本匹配时表现优异。简单来说,KMP 算法比 BF 算法有更高的效率,是 BF 一个升级的算法。

2024-04-19 17:38:58 4479 70

原创 Java 笔试强训篇- Day1

他每次“点击”,可以把字符串中相邻两个相同字母消除,例如,字符串"abbc"点击后可以生成"ac"。牛牛想把字符串变得尽可能短。他想知道,当他点击了足够多次之后,字符串的最终形态是什么?一个字符串,为“点击消除”后的最终形态。若最终的字符串为空串,则输出0。一个字符串,仅由小写字母组成。(字符串长度不大于300000)但相同而不相邻、不相同的相邻字母都是不可以被消除的。牛牛拿到了一个字符串。

2024-04-16 16:15:46 2482 38

原创 JavaEE 初阶篇-线程安全的集合类、多线程环境使用 ArrayList、队列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的区别)

只对写操作进行加锁,加锁的方式仍然是 synchronized ,但是不是锁整个对象,而是“锁桶”,每一个链表的头节点作为锁对象,大大降低了锁冲突的概率。由于哈希表是由数组与链表或者红黑树组成的,数组的长度很长,因此相对链表的长度来说,链表的长度就很短了,所以在多线程中,对数组中的某一个链表大概率是不会冲突的,因此即使每一个链表都上锁了,这个锁也大概率是偏向锁,大概率是没有加锁和解锁的开销。扩容期间,新老数组同时存在。是一个线程安全的集合类,所有对 HashTable 的操作都是同步的,即线程安全的。

2024-04-14 22:33:41 1673 24

原创 JavaEE 初阶篇-深入了解 CAS 机制中的 ABA 问题、synchronized 加锁过程、 ReentrantLock 与 synchronized 的区别、常见信号量操作等

举个例子讲述 ABA 的问题:假设:现在有两个线程 T1、T2 ,对共享变量 num 进行操作,num 的初识值为 A。接下来,T1 线程想要将 num 的值改为 Z ,根据 CAS 机制可知,首先将 num 从主内存中读取到 T1 线程的工作内存中,接着就是比较当前主内存的 num 中的值与工作内存中的值是否相同。如果主内存 num 的值还是 A 时,则默认会认为没有其他线程“动过”该变量,这时就可以将 num 的值改为 Z 后,交换到主内存中。

2024-04-14 20:38:22 1083 3

空空如也

空空如也

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

TA关注的人

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