- 博客(45)
- 问答 (1)
- 收藏
- 关注
原创 【RocketMQ】 springboot 3.x 注入 RocketMQTemplate 失败
SpringBoot3.x 使用 @Resource 注入RocketMQTemplate 失败,需要在启动类上手动导入自动配置类。
2024-12-04 21:01:57
470
原创 Java 类加载机制和对象的创建过程
在Java中,类加载和对象创建是两个至关重要的过程。理解这两个过程不仅有助于开发高效的Java应用程序,还能帮助开发者更好地掌握Java的内存管理与性能优化。本文将详细描述这两个过程。
2024-10-24 14:07:17
643
1
原创 线程池常见面试题
对于Runnable任务,上层无法直接感知异常,除非通过其他手段捕获。对于Callable任务,通过可以感知到异常。如果需要全局处理异常,可以自定义线程池的异常处理机制,比如通过设置线程的未捕获异常处理器,或者扩展的方法。
2024-10-23 17:01:22
820
原创 浏览器访问一个网址的过程
DNS 解析:浏览器首先会解析出域名,然后查找域名对应的 IP 地址。依次访问浏览器缓存 → 操作系统缓存 → hosts 文件 → 本地 DNS 服务器 → 根域名服务器 → 顶级域名服务器 → 权威 DNS 服务器,直到得到 IP 地址。建立 TCP 连接:浏览器通过 DNS 解析得到服务器的 IP 地址后,会通过 TCP 协议与服务器建立连接。这个过程包括 TCP 的三次握手。发送 HTTP 请求:连接建立后,浏览器会向服务器发送 HTTP 请求。请求中包括请求行(方法
2024-10-11 23:23:56
1571
原创 什么时机用mysql,什么时机用redis,什么时机用本地内存
Redis 的读写速度比 MySQL 的 buffer pool 快,主要是因为 Redis 专门为内存中的高效读写设计,避免了磁盘 I/O、复杂的事务管理和锁竞争。同时,Redis 的数据结构和单线程事件驱动模型都高度优化,减少了读写路径上的开销。而 MySQL 的 buffer pool 虽然缓解了磁盘访问的瓶颈,但由于其设计目标是关系型数据库,包含更多复杂的数据管理逻辑和一致性保障机制,因此无法像 Redis 那样纯粹追求速度。
2024-10-11 15:35:14
527
原创 系统设计,如何设计一个秒杀功能
1、 秒杀活动即将开始时,用户会不断刷新页面,前端资源的访问也会消耗大量的资源。可以把这部分压力给到 CDN 厂商。4、 打到后端服务后可以利用分布式缓存(Redis)或本地缓存(Caffeine)承接读写。2、 秒杀的大部分请求都是无效的,可以在前端设置随机限流,使部分请求直接返回失败。3、 对于发出的请求再次通过 lvs、nginx、sentinel 层层限流。库存扣减需要防止并发导致的超卖。使用这个语句会产生热点行问题,压测下性能不高。通过预约、预售等方式避免秒杀的高并发流量。
2024-10-06 21:23:52
787
原创 Spring IoC 工作流程
Spring IoC 容器首先需要从配置源(XML、Java配置类、注解)中读取和解析 Bean 的定义。流程如下:XML 文件加载:如果使用 XML 文件,容器会从配置文件中找到 标签,并解析每个 Bean 的定义,包括其类名、作用域(如单例或原型)、初始化方法、依赖的注入方式等。
2024-09-25 21:44:51
1011
原创 HashMap 常见面试题(含1.7 和 1.8 对比)
HashMap 是基于哈希表的数据结构,用于存储键值对 (key-value)。其核心是将键的哈希值映射到数组索引位置,通过数组+链表(在 Java8及之后是数组 +链表+红黑树)来处理哈希冲突。Hashmap 使用键的 hashcode()方法计算哈希值,并通过 indexFor 方法确定元素在数组中的存储位置。哈希值是经过一定扰动处理的,防止哈希值分布不均匀,从而减少冲突。HashMap 的默认初始容量为 16,负载因子为 0.75。
2024-09-25 15:05:19
925
原创 MySQL update 一条语句的过程
事务执行过程中会先把日志写到 binlog cache 中,事务提交时再把 binlog cache 写到 binlog 文件(内核空间内存)中。通过参数可以控制执行 fsync 的时机(从内核空间内存到磁盘)。脏页写入磁盘的操作与事务提交是解耦的。
2024-09-22 14:47:11
772
原创 synchronized 原理
JVM的线程和操作系统的线程是对应的,重量级锁的Markword里存储的指针是这个monitor对象的地址,操作系统来控制内核态中的线程的阻塞和恢复,从而达到JVM线程的阻塞和恢复,涉及内核态和用户态的切换,影响性能,所以叫重量级锁。偏向锁:偏向锁会在锁对象头的Markword的偏向线程ID里存储当前线程的操作系统线程ID,偏向锁标识位是1,锁标识位是01。
2024-09-19 18:46:54
460
原创 JMM 指令重排 volatile happens-before
在单线程程序中,操作系统会通过三个步骤对源代码进行指令重排,提高代码执行的性能。但是在多线程情况下,操作系统“盲目” 地进行指令重排可能会导致我们不想看到的问题,如经典双检锁单例模式。那么我们就需要给操作系统定一些规矩或者上一些手段让他不要随意地指令重排。但是由于操作系统和硬件的差异,内存访问的差异,会造成相同的代码运行在不同的系统上会出现各种问题。为了屏蔽掉各种硬件和操作系统的内存访问差异,以实现让java程序在各种平台下都能达到一致的多线程并发效果,所以有了 Java 内存模型(JMM)。
2024-09-12 21:27:45
1019
原创 BeanFactory vs. ApplicationContext
更适合轻量级场景,提供基本的IoC功能;而是功能更强大、使用更广泛的容器,提供了事件机制、国际化等高级功能,适合大多数企业级应用开发。
2024-09-10 23:21:12
438
原创 Java 创建对象方法的演变
通过 ClassPathXmlApplicationContext 调用 Bean,可以通过三种方式调用:id(需要强转)/ class(需要 bean 是单例的)/ id + class。第二段是我们自己的 bean,需要给 bean 指定 id(对象的唯一标识,不可重复),class(实现的类的全限定名),属性赋值(set 后面的属性)。
2024-09-10 22:55:36
226
原创 TCP 为什么是三次握手,而不是两次或四次?(通俗易懂)
第二次握手:客户端接收到服务端的 SYN 和 ACK,知道了自己的发送能力,接收能力,对方的接收能力,发送能力都没问题,也就是说两次握手客户端已经就绪(ESTABLISHED)了。第三次握手:服务端接收到客户端的 ACK,知道自己的发送能力和对方的接收能力没问题,服务端也就绪(ESTABLISHED)了。第一次握手:服务端接收到客户端的 SYN,知道了对方的发送能力和自己的接收能力没问题。TCP 三次握手是为了保证:让客户端和服务器都知道自己和对方的发送和接收都没问题。三次就够了,四次浪费。
2024-09-10 15:48:39
435
1
原创 IO 多路复用,select,poll,epoll
实际上每个 socket 都有一个等待队列,当 线程调用 select 后,线程会被添加到 socket 的等待队列中,当 socket 有事件发生,操作系统会遍历 socket 的等待队列,将等待的线程唤醒,之后返回就绪的 socket 的数量,然后线程再遍历 socket ,处理打了标记的 socket。(线程进入阻塞状态后必须被唤醒才能继续执行,否则操作系统返回了线程也不会执行。这也是 select 性能低的原因,因为每次调用都要将线程加入到等待队列,每次返回都将线程从等待队列中移除。
2024-09-09 23:47:55
469
原创 Spring 循环依赖原理及解决方案
循环依赖指的是一个实例或多个实例存在相互依赖的关系(类之间循环嵌套引用)。上述例子中 AService 依赖于 BService,BService 也依赖了 AService,这就是两个对象之间互相依赖。循环依赖还包括 身依赖、多个实例之间相互依赖(A依赖于B,B依赖于C,C又依赖于A)。
2024-09-09 01:14:01
1278
原创 Spring Bean 的生命周期
实例化完成后,Spring 会进行依赖注入,包括将属性值注入到 Bean 的字段中。实例化阶段通过反射机制创建一个 Bean。
2024-09-08 21:31:19
908
原创 HTTP1.0 到 HTTP3.0 的变化
将传输的数据分成一个个二进制帧,可以独立传输,每个帧的头部会携带 Stream ID 信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息。服务端不再是被动地响应,可以主动向客户端发送消息、推送额外的资源,比如客户端请求网页,服务端会将相关的 CSS、JavaScript 或图片文件等。在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,就不用重复发送同样字段了,只发送索引号,减少数据量提高速度。允许同时通过一个连接并行传输多个请求和响应,解决了队头阻塞问题。
2024-09-07 14:43:01
497
原创 Spring Boot 自动装配原理及 Starter 实现
通过 Spring Boot 启动类上的 @SpringBootApplication 注解,Spring 就可以遍历所有 META-INF 的 spring.factories 文件中的配置类,并根据 @EnableAutoConfiguration 的条件选择是否将其注册为 bean。创建 Spring Boot 工程,添加项目需要的依赖,Spring Configuration Processor 这个依赖可以帮助开发者自动生成配置的的代码提示。方便快捷地引入依赖或者配置属性。
2024-09-04 18:02:31
1331
2
原创 MySQL 的 undo log,redo log,binlog 总结
事务执行过程中,先把日志写到 binlog cache(在用户空间的内存),事务提交时会把 binlog cache 写入到 binlog 文件(在内核空间的内存)中,并清空 binlog cache。在事务提交时,只需将 Redo Log 持久化到磁盘就能保证发生断电的情况下能够将数据恢复到最新状态,不需要等 Buffer Pool 的脏页数据刷盘。MySQL 不能再执行修改操作,会停下来先将 Buffer Pool 中的脏页刷盘,之后擦除掉 Redo Log 的旧记录。顺序写比随机写高效的多。
2024-08-28 20:34:52
760
原创 同步、异步、阻塞和非阻塞的理解
例如,使用 Mono 或 Flux 来处理流式数据,这种方式下,数据的处理是异步的,并且不会阻塞调用线程。这是一种同步方式,因为任务按顺序执行,但并不阻塞其他任务的执行。这意味着任务本身是异步执行的,但在你获取结果时,线程会被阻塞。在异步调用中,如果回调函数内执行了阻塞操作(如 I/O 操作),这会导致尽管任务是异步的,但在处理结果时仍然会阻塞线程。异步指的是对于每个请求,不需要等待上一个请求完成就可以进行下一个请求,上一个请求完成后会通过回调机制通知。非阻塞侧重于等待请求期间,可以执行其他请求。
2024-08-28 18:34:33
325
原创 前后端跨域问题解决方案
设前端所在服务器 IP 为 IP1,后端所在服务器 IP 为 IP2,前端项目绑定了域名。比如你写的是域名,那么访问就要用域名访问,用 IP 地址访问就无法携带 cookie。在 requestConfig.js 中加入requestConfig。:baseuURL 的xxxx写的是什么,访问的时候就要用什么去访问。本篇文章是基于自己踩的坑记录的一些解决方案,如有错误,敬请指正!同理,写的是 IP 地址,用域名访问也不会携带 cookie。后端框架:SpringBoot。编写跨域 Config。
2024-08-16 16:40:13
186
原创 【JAVA】String、StringBuilder和StringBuffer的区别,看完忘不了
在Java编程中,处理字符串是一个常见的任务。Java提供了几种不同的类来处理字符串,其中最基本的是String,另外两个是和。
2024-05-17 13:43:42
387
1
原创 【力扣】用栈实现队列&&用队列实现栈 (用deque实现)
使用两个栈实现先入先出队列。假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)一个栈stackIn模拟进队,一个栈stackOut模拟出队。
2024-05-08 19:48:59
210
1
原创 【JAVA】网络编程-实现离线留言
在韩顺平老师的多用户即时通信系统中实现离线留言,主要的思想是:当客户端A向客户端B发送消息时,判断客户端B是否在线,在线则直接发送,不在线则创建一个线程保存消息,等待客户端B上线后再发送给他。
2024-04-02 21:54:21
417
1
原创 【JAVA】 常用IO流基本操作
注意:FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!和Reader和Writer类似,只不过是通过String.getBytes()将字符串转为字节再传输。相关API: String类:toCharArray:将String转换成char[]和Reader和Writer类似,只不过是把char数组改为byte数组。在读取数据时,读取数据的值和数据类型(反序列化)在保存数据时,保存数据的值和数据类型(序列化)
2024-03-31 15:25:03
1788
1
原创 【JAVA】集合,Collection接口和Map接口的实现类及其常用方法
add:添加单个元素remove:删除指定元素contains:查找元素是否存在size:获取元素个数isEmpty:判断是否为空clear:清空addAll:添加多个元素containsAll:查找多个元素是否都存在removeAll:删除多个元素iterator:用于遍历Collection集合中的元素List接口额外的常用方法1)List集合类中元素有序(添加顺序和去除顺序一致)、且可重复2) List集合中每个元素都有其对应的顺序索引,即支持索引。add(int index,
2024-03-18 00:57:01
2081
1
原创 【力扣】15.三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i!= k ,同时还满足 nums[i] + nums[j] + nums[k] == 0。如果nums[i]+nums[j]+nums[k]==0,记录这个组合,由于不可以包含重复的三元组,j需要向右移,直到不和之前的值重复;解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0。输出:[[-1,-1,2],[-1,0,1]]
2024-03-17 21:11:51
258
1
原创 【力扣】142.环形链表Ⅱ
可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。:从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。设置一个visited集合,存放已经遍历过的节点,如果当前节点已经在这个集合中,说明这个节点就是环的入口。给定一个链表的头节点 head ,返回链表开始入环的第一个节点。
2024-03-17 16:00:26
251
1
原创 【JAVA】Map的遍历方式,Node和Entry的关系
通过EntrySet 来获取k-v。EntrySet指的是map.entrySet(),其中存放着Map.Entry。Map.Entry对象存放着一组key和value,可以通过getKey和getValue方法获取。先取出所有的Key,通过Key取出对应的Value。把所有的values取出。
2024-03-16 17:46:50
634
1
原创 【JAVA】HashSet机制理解
HashSet的底层是HashMap,第一次添加时,table数组扩容到16,当table中的元素个数到达临界值(table.size*loadFactor(默认是0.75))时,table.size扩容到原来2倍。:如果有一条链表的元素个数到达8,但是table的大小没到64,再向这个链表中添加一个元素(这条链表有9个元素),不会触发树化,但是会将table的大小扩容到原来2倍,即使table中的元素个数还没到达临界值。2)当name和age的值相同时,认为是相同员工,不能添加到HashSet集合中。
2024-03-16 01:09:28
287
1
原创 【力扣】206.反转链表&24.两两交换链表中的节点
4)first的next指向下一需要反转的节点(因为第一个节点在反转后肯定是最后一个节点,当第一个节点的next为None时即全部反转)。3)dummy的next指向反转节点(dummy的next需要一直指向头节点,因为我们的程序是以dummy.next作为返回结果);每次反转一个节点(对于12345,先反转成21345,再反转成32145…2)反转节点的next指向头节点(这样反转节点就成头节点了);1)保留反转的下一节点,因为反转节点的next会进行改变;输入:head = [1,2,3,4,5]
2024-03-14 00:18:01
436
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人