自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 JMM Java内存模型

多线程之间要配合,谁先谁后要互相让其他线程感知,要遵守Happens-Before,才能满足多线程之间的可见性。否则就不能对另一个操作可见或者禁止代码重排序。

2024-03-29 01:21:37 340

原创 LockSupport与线程中断机制

中断机制是个协商机制一个线程不应该由其他线程来停止方法1、2用 volatile或AtomicBooleant2对t1发起协商中断底层是调用interrupt0():发现interrupt0是native方法,调用的是底层操作系统或是第三方的函数库就是把当前的中断标志位从false设置为true,并不是立刻停止当前线程。如果某个线程正在调用阻塞方法,此时调用interrupt()会清除中断状态,立即退出阻塞状态并抛出中断异常。被中断返回true,否则返回false底层还是调的native方法小结:不会,仅仅

2024-03-29 01:19:43 958

原创 Synchronized锁、公平锁、悲观锁乐观锁、死锁等

hpp作为文件名扩展名的一种约定,用于区分C++的头文件和C的头文件(通常使用.h作为文件名扩展名)。:当系统中的资源不足时,例如内存、文件句柄、网络连接等,进程(线程)可能会因为无法获取所需的资源而陷入死锁。当采用非公平锁,当1个线程请求获取同步状态,然后释放同步状态,所以在此刻该线程获取同步状态的概率就会变得很大,减少了线程切换的开销。:如果进程(线程)在获取资源时没有正确地管理和释放资源,或者资源的分配策略不合理,可能会导致资源的浪费和争夺,最终导致死锁。

2024-03-29 01:18:34 912

原创 对象内存布局

类型指针是对象头中的一个重要字段,用来指示对象的实际类型。在Java中,对象的类型信息是在类加载阶段确定的,每个对象在创建时都会分配一个指向其类型的类型指针。这个类型指针在对象头中的位置是固定的,并且在对象的生命周期中不会改变。类型指针的存在使得虚拟机可以在运行时确定对象的实际类型。所以New一个对象 没有其他信息 就是16字节。每次new对象的统一的多个实例对象的模板。虚拟机要求对象起始地址必须是8字节整数倍。存放类的属性信息,包括父类的属性信息。指向方法区的一个模板。

2024-03-29 01:17:43 256

原创 原子增强类(18罗汉)

Unsafe类,线程类内部定义的随机的一个probe主要用来得到线程的hash值极端情况:强制初始化如果线程的hash值为0是不允许的,就像每个新入职的员工都要有工号。重新给一个hash值,并设置为true可以重新参与竞争。1.假设此时该cell数组的这个坑位的不为null了,不走这个if了。2.假设上一步cas是失败了,false取反是true,重新设置为true。3.重新计算hash,重新进行竞争。也就是一开始竞争失败了,没事,重新刷一次hash值,继续争。

2024-03-28 13:33:43 856

原创 动态代理大总结

类型的bean 支持Order注解排序 放入list】然后还会找到@Aspect切面【遍历所有bean 看哪个类上有@Aspect注解 】里的。

2024-03-27 17:48:35 797

原创 Sentinel源码解析

整个Sentinel就是个大的try-catch,在服务端【dashboard】配置一系列规则,推到客户端内存的链条里面去,当我调用客户端方法的时候,都会经过链条,如果在这个过程中抛异常,会根据异常种类调用不同的对应的降级方法。一开始end指向first,end的next也就是first的next就指向了新加进来的slot,然后end重新指向新加进来的slot。中间的if逻辑是大概率不会走的。当这个链条也通过了,就会执行真正的业务方法========+++++++=================

2024-03-27 16:29:39 1277

原创 代码写错分支

第三步:从暂存区中取出保存到正确的分支中。如果还没有push commit 代码。git push origin 分支名。执行还没有push commit的步骤。第一步:将所修改的代码提交到暂存区。git checkout 分支名。如果已经push到远程仓库。第二步:切换到正确的分支。

2024-03-26 11:46:08 149

原创 第4章 虚拟机栈

由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的【如果设计成基于寄存器的,和cpu耦合度高,性能会有所提升,因为可以对具体的CPU架构进行优化,但是跨平台性大大降低】。优点是跨平台,指令集小【8位】,基于寄存器【指令集16位】,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令。具体问题具体分析如果只有一个线程才可以操作此数据,则必是线程安全的。如果有多个线程操作此数据,则此数据是共享数据。

2024-03-26 10:44:38 572

原创 Rocket mq

其实每个NameServer节点之间是互相独立的,没有任何信息的交互,都是全量数据,每个Broker都会往3个NameServer同时注册,他们3个NameServer组成集群的唯一作用是客户端可以指定3个NameServer,如果有其中一个挂了会自动换成另一个NameServer。如果此时发1000条消息,那只有master才会接收到消息,slave只会负责从master上备份消息 ,那此时broker-b的从节点就不会接收消息,所以保证了安全性,但是服务的可用性就降低了【必然有一个取舍】

2024-03-26 10:42:13 1041

原创 实例化的一些细节

这样,当通过 Parent 类型的引用调用 getValue() 方法时,实际上调用的是桥接方法,该方法会转而调用 Child 类中重写的 getValue() 方法。①首先会判断是不是一个候选类:比如String类就不是,如果某个类是以java.开头的就不需要找注入点,java.开头的类代表Java平台的核心类,以确保Spring容器的职责明确,专注于它应该管理的组件。2.1通过反射这里会拿到2个注入点,这是不对的,所以会排除掉桥接方法,然后找到被桥接的那个方法(自己实现的那个方法)去判断。

2024-03-26 10:21:05 576

原创 SpringBoot自动配置

SpringBoot中众多的条件注解,都是基于Spring中的@Conditional来实现的,所以我们先来用一下@Conditional注解。先来看下@Conditional注解的定义:/***/Class<?@OverrideConditionContext:表示条件上下文,可以通过ConditionContext获取到当前的类加载器、BeanFactory、Environment环境变量对象。

2024-03-26 10:18:39 2367

原创 Redis+Lua脚本+AOP+反射+自定义注解,打造内部基础架构限流组件

1.开发自定义限流注解给全团队赋能共用,一个注解搞定2.可配置【时间窗口内可以随意灵活调整时间和次数】 + 可拔插3.支持高并发【redis下干的】且满足事务一致性要求,lua脚本1.自定义注解RedisLimitAnnotation实现业务解耦2.高并发实时配置下的LuaScript处理3.自定义AOP切面类。

2024-03-26 10:16:28 486 1

原创 Spring aop 源码(上)

Import 注解主要用于导入其他配置类或组件。当你想把一个或多个类作为Bean注册到Spring容器中时,可以使用 @Import 来引入这些类。这个注解通常用在配置类上,可以导入其他配置类或普通的组件类。使用 @Import 注解时,导入的类将作为一个完整的类注册到Spring容器中,即Spring会为这些类创建Bean实例。这个注解对于模块化配置非常有用,因为它允许你将配置分散到多个配置类中,然后将它们组合到一起。

2024-03-26 10:15:17 1162

原创 Spring Aop 源码解析(下)

运行在GraaJVM,开启了优化isOptimize,isProxyTargetClass传的代理是不是个类【而不是接口】,hasNoUserSuppliedProxyInterfaces看proxyFactory是不是调用了addInterface()方法,如果以上符合任意一个就会用cglib动态代理,否则用的就是jdk动态代理。所以在ProxyFactory生成代理对象前会去判断用的哪个动态代理,选定好技术后再调用getProxy()去产生真正的代理对象。

2024-03-26 01:55:24 872 1

原创 Sentinel

给B加上4秒钟80次请求要等4秒钟结束了,A服务才能正常访问,因为B服务QPS太高,所以把A限流了先不引入@SentinelResource注解没有引入触发限流保护不想用默认返回提示因为byResource()方法没有返回参数,所以在handlerBolckHandler里要加上BlockException。如果有参数直接拷贝。正常访问触发限流变成自己的提示了。

2024-03-25 02:17:14 881

原创 动态代理源码分析

传入代理类和你在Enhancer里面设置的方法拦截器传进去,然后把刚才那个设置ThreadLocal的方法名字,和代理类传进去,找到Method对象,然后用反射,因为是static,所以obj是null,把方法拦截器座位参数callbacks传进去最后就成功设置到ThreadLocal这个属性上面去有值之后,接下来就会产生代理对象,代理对象执行test方法就会拿到刚才设置的Callback,然后执行Callback里的方法拦截器方法,从而执行到我们所设置的intercept方法里面去。

2024-03-21 15:04:11 993

原创 Spring Bean 依赖注入(下)

都只会找到一个要注入的bean,然后构造一个shortcutDependencyDescriptor对象(依赖描述器的子类)作为缓存。缓存的是字段的信息,字段的类型和bean的名字。如果第二次来注入,直接把缓存好的对象传到方法里直接拿缓存好的beanName去得到bean对象@Value下面还有一步,根据类型把所有的beanName找出来。

2024-03-20 17:50:00 886

原创 Spring循环依赖

spring创建bean的时候是串行去创建的,而不是并发的循环依赖出现的场景解决方法:三级缓存,也就是3个Map增加中间人(缓存)打破循环A对象有个B对象的成员变量,B对象有个A对象的成员变量,此时A对象要进行属性填充,但B对象还没有创建好,此时就需要去创建B对象,但是此时A对象也没创建好,于是陷入循环。。。这时候,就有个办法,A对象生成后马上把自己放入到一个map中,这样B对象就能从这个map里取到A对象执行后续操作,且操作的是同一个对象。

2024-03-19 17:58:23 673

原创 Spring Bean生命周期源码解析(上)

构造方法里会new一个扫描器(扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition)和BeanDefinition读取器(可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解)Spring5.3新增的接口就两个实现类什么都没做Jdk9或11以后得新特性JFR 就是 Java 的黑匣子主要用于记录这行代码的运行时间是多少第三行记录结束refresh()方法里有个完成Bean工厂初始化的方法这个方法

2024-03-19 15:53:22 590

原创 SpringBoot自动配置

SpringBoot中众多的条件注解,都是基于Spring中的@Conditional来实现的,所以我们先来用一下@Conditional注解。先来看下@Conditional注解的定义:/***/Class<?@OverrideConditionContext:表示条件上下文,可以通过ConditionContext获取到当前的类加载器、BeanFactory、Environment环境变量对象。

2024-03-19 15:50:45 706

原创 NGINX配置

会有1个master进程和多个worker进程,master用来管理worker进程,多个worker进程会竞争客户端请求,一个请求只会被1个worker处理【一般和CPU核数一致 超过的话产生不必要的上下文切换】。用户访问的是NGINX服务器,NGINX再转发到应用服务器上,Tomcat把相应结果返回给NGINX,NGINX再传给用户,相当于NGINX是中间商。每个worker支持的最大连接数,如果是反向代理,需要耗费掉2个连接,一个是NGINX和客户端,一个是NGINX和服务器端。

2024-03-19 14:24:08 288

原创 链表的算法

resize方法依托的是底层静态数组,链表理论后面可以无限指向下一个节点。链表是真正的动态数据结构。1.解决了数组扩缩容问题。

2024-03-18 00:55:36 136

原创 四级缓存实现

多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻Server端的压力,提升服务性能。一级缓存:1.CDN:内容分发网络二级缓存:2.NGINX+Lua脚本+OpenResty服务器 负载均衡反向代理【静态和转发】三级缓存:JVM进程缓存【本地缓存Caffeine】四级缓存:Redis缓存五级缓存:Mysql集群+主从复制Mysql现在是Caffeine===》(程序)====》Redis===》(cannel 阿里现成的工具 监听mysql)===》Mysql。

2024-03-17 21:51:18 882

原创 队列的算法

不要往前移动,减少复杂度,采用双指针,front和tail,就可以解决这个问题。如果不断入队和出队,前面就会空了一大截,前面一大片空间就浪费了。tail + 1 == front 就是满了,要浪费1个空格子。front == tail,可能是空也可能是满,防止歧义,循环队列先插10万个数,再出队10万个数耗时0.01秒。front指向队首,tail指向队尾的下一个存储单元。数组队列先插10万个数,再出队10万个数耗时4.4秒。①队首出列后,后面的全部向前移动一个补缺。主要是尾指针移到末尾后又会移动到队首。

2024-03-16 01:17:41 210

原创 Redis为什么那么快?

Redis从其早期版本开始就使用了IO多路复用技术。IO多路复用是Redis高性能的关键特性之一,它允许Redis服务器同时处理来自多个客户端的连接和请求,而不是为每个连接创建一个线程或进程。IO多路复用使得单线程的Redis能够使用非阻塞I/O操作,这样Redis服务器可以在不同的连接之间高效切换,只要有数据可读或可写,就处理相关的请求。这种方式让Redis能够充分利用其单线程模型,同时保持高吞吐量和低延迟。

2024-03-15 16:43:58 690

原创 Redis管道和发布订阅

第三点:linux访问redis再得到返回。

2024-03-15 15:03:53 146

原创 Redis事务

如果你使用的是 Redis 的最新版本,上面提供的一次性设置多个字段的命令将正常工作。如果你使用的是 Redis 的早期版本,你可能需要分两次执行 HSET 命令,每次设置一个字段。在这个例子中,user:001 是哈希表的名称,可以看作是一个用户对象,其中 id 和 uname 是该用户对象的两个属性。此时balance是110,开启了监控,此时我想把balance设置为200,但是此时有人比我先行一步。一次在跟数据库的会话当中, 所有执行的sql要么一起成功,要么一起失败。balance是银行余额。

2024-03-15 14:16:47 361

原创 skiplist跳表

跳表是可以实现二分查找的有序链表跳表 = 链表 + 多级索引。

2024-03-15 10:52:53 180

原创 大根堆排序

堆是完全二叉树,分为大根堆和小根堆。

2024-03-14 14:46:32 460

原创 力扣75题 算法

输入:nums1 = [1,2,3], nums2 = [2,4,6] 输出:[[1,3],[4,6]] 解释: 对于 nums1 ,nums1[1] = 2 出现在 nums2 中下标 0 处,然而 nums1[0] = 1 和 nums1[2] = 3 没有出现在 nums2 中。输入:nums1 = [1,2,3,3], nums2 = [1,1,2,2] 输出:[[3],[]] 解释: 对于 nums1 ,nums1[2] 和 nums1[3] 没有出现在 nums2 中。

2024-03-14 01:33:18 894

原创 二叉树算法

4.接下来2弹出,此时节点不是统计的那层了,做结算Max,当前层更新++,当前节点数重新置为1(因为发现的节点肯定是存在的,肯定是1)2弹出,2有右树,右树5压栈,5无左子树,于是弹出并打印,再把5的右树压栈,都没有,把2弹出。2.先弹出1,当前层从map知道是在1层,当前层还是正在统计的那层,1==1,所以count++,nodes变成1。弹出7,放入收集栈,此时压7的左和右,但都是null,于是弹出6,放入收集栈。2出栈,2有右树5,把5压入栈,再把5所有左数压入栈里,6进栈7进栈。

2024-03-14 01:32:20 339

原创 快速排序算法

总拿最后一个数做划分,划分好最后一个数和大于区的第一个数做交换,然后在小于等于5区域和大于5区域继续往复循环操作,都取各自的最后一个数作为基准数。每次排序都能搞定一堆等于5的区域。只要最后一个数和大于区的第一个数做交换。L到R随机选个数和最后位置做交换,拿最后位置做划分。然后左右侧以最后一个数作为基准数,继续做递归。partition后就返回12和13,L和R的索引分别是10和15。

2024-03-14 01:29:48 557

原创 算法的渐进时间复杂度

1.初始化【构造注入,懒加载】// 数组中实际元素个数int size;this(10);// 增 塞到数组最后面// 假设实际容量已经最大了// 法①:数组满了无法出入// 法②:扩容size++;// 法② 复用// 加到中间// 法①:数组满了无法出入// 法②:扩容// 负数索引和超过边界都无法插入数据// 法①:抛异常,不在数组边界内i >= size;i--){// 不可以忘记!!!!size++;// 加到开头add(0,e);

2024-03-14 01:29:12 495

原创 SpringBoot启动过程

检查Springboot是否配置了懒加载,如果配置了就会往spring容器添加一个懒加载beanPostProcessor修改spring bean定义的懒加载全部设置为true。2.有可能不是web应用,也能是Springboot java应用【recative是响应式的 Servlet是阻塞式的 古老的web类型 都能接受web请求的】Springboot默认的ApplicationStartingEvent的starting方法会发布广播一个ApplicationStartingEvent事件。

2024-03-13 16:40:30 1052

原创 Sharding sphere分库分表

需要物理自己实现分表分库,然后通过配置文件配置。

2024-03-13 16:29:59 1337

原创 DDD领域模型驱动

DDD架构:api层:api请求方式,透传【传递参数】,几个业务对应api业务层:做编排,业务里要有哪些服务,执行顺序是什么,以及怎么做领域层:负责领域内调用,然后领域怎么划分Dao层:数据库操作【或者另外一个应用 数据源之类的】遵守原则:①允许跨层调用②业务细节放在领域层,业务层负责编排,一行一行对应着一个调用,最好不要有其他代码了③领域层禁止互相调用,可以从包名入手,直接对领域进行分割,就算代码冗余也没事。④事务管理:放业务层有大事务风险,放在领域层会有一致性问题的风险。

2024-03-13 15:54:21 391

原创 AQS源码分析

AQS通过内部的FIFO队列来管理线程的获取和释放锁的顺序,它使用状态(state)变量来控制同步器的状态,以及定义了一系列用于操作状态和管理线程排队的方法。当取消节点的前驱节点被重新设置为该取消节点的前驱的前驱节点时,取消节点实际上已经被从等待队列中“跳过”,即在逻辑上被忽略了。此时的pred还是节点B,也就是节点B的next指向了节点C,搞完收工 return,不会执行下面的enq!尾节点此时还是指向节点B的,这里期望是tail,没毛病,期望是自己,然后修改为节点C,也就把tail指向了节点C。

2024-03-12 17:43:14 1258

原创 CAS 比较和交换

可以把自己定义的类包装成原子类型。

2024-03-12 17:02:16 1114

原创 Volatile与JMM

如何保证的?内存屏障当写一个Volatile变量的时候,JMM会把该线程对应的本地内存共享变量值立即刷新回主内存。当读一个Volatile变量的时候,JMM会把本地内存置为无效,重新回到主内存中读取最新共享变量。内存屏障前的所有写操作都要写回主内存内存屏障之后的所有读操作都能获得内存屏障之前的所有写操作的最新结果(实现了可见性)看到写屏障:把这个指令之前的全部写回主内存看到读屏障:保证了读取到的数据都是最新的写指令之后插入读指令之前插入度屏障写屏障读写混合Unsafe.class 一定会对应 Unsafe.

2024-03-12 16:56:37 742

空空如也

空空如也

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

TA关注的人

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