- 博客(41)
- 收藏
- 关注
原创 JVM垃圾回收器详解
垃圾回收器的组合关系虽然很多,但是针对几个特定的版本,比较好的组合选择如下:JDK8及之前:ParNew + CMS(关注暂停时间)、Parallel Scavenge + Parallel Old (关注吞吐量)、 G1(JDK8之前不建议,较大堆并且关注暂停时间)JDK9之后:G1(默认)从JDK9之后,由于G1日趋成熟,JDK默认的垃圾回收器已经修改为G1,所以强烈建议在生产环境上使用G1。(此处)并行和并发概念补充并行(Parallel)
2024-07-10 11:56:02
655
原创 JVM之垃圾回收算法详解
如果允许,那会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次 Minor GC,尽管这次 Minor GC 是有风险的;比如在新生代中,每次收集都会有大量对象死去,所以可以选择”标记-复制“算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。没有一个垃圾回收算法能兼顾上述三点评价标准,所以不同的垃圾回收算法它的侧重点是不同的,适用于不同的应用场景。:如果存活对象数量比较大,复制性能会变得很差【老年代存活的多,把那么多复制很费事,所以适合新生代】
2024-07-09 10:26:53
1516
原创 Redis持久化详解
Redis的持久化虽然可以保证数据安全,但也会带来很多额外的开销,因此持久化请遵循下列建议:用来做缓存的Redis实例尽量不要开启持久化功能【提高查询效率的不需要持久化,查询时再写一遍就好。对于安全性要求高的,比如分布式锁、库存、验订单的流水需要持久化(可以专门放在一个redis实例)】建议关闭RDB持久化功能,使用AOF持久化【可以混合。rdb会丢失数据】利用脚本定期在slave节点做RDB,实现数据备份设置合理的rewrite阈值,避免频繁的bgrewrite。
2024-07-03 21:35:37
944
原创 Redis主从集群下的脑裂现象
降级措施,将数据暂时写入本地缓存和磁盘中,在一段时间(等 master 恢复正常)后重新写入 master 来保证数据不丢失,也可以将数据写入 kafka 消息队列,等 master 恢复正常,再隔一段时间去消费 kafka 中的数据,让将数据重新写入 master。min-slaves-to-write x,主节点必须要有至少 x 个从节点连接,如果小于这个数,主节点会禁止写数据。主节点短暂失联,数据写入,重新选举的主节点上任后原主节点变从节点,第一次数据同步会清除从节点全部数据再进行。
2024-06-30 01:11:24
242
原创 ForkJoin
任务拆分:将一个大任务拆分为算法上相同的小任务,直至不能拆分可以直接求解。ForkJoin 使用 ForkJoinPool 来启动,是一个特殊的线程池,默认会创建。,避免和队列所属线程发生竞争,但是队列中只有一个任务时还是会发生竞争。难在如何拆分,后面JDK8就封装到stream的api了,并行流。,把每个任务的分解和合并交给不同的线程来完成,提升了运算效率。,适用于能够进行任务拆分的 CPU 密集型运算,用于。工作窃取算法允许空闲的线程从其它线程的双端队列中。Fork/Join:线程池的实现,体现是。
2024-06-29 23:08:08
374
原创 划分子网、子网掩码、地址范围、网络地址和广播地址。
一公司原来使用 192.168.1.0/24 这个标准网络,现在想为公司的每个部门(共六个)单独配置一个子网,其中最大的部门要分配 IPv4 地址的数量不超过 25 个。192.168.1.0 / 27 0~31(0 + 31) 192.168.1.31(31 + 0网络号 + 全1)网络号取3位,所以可以取000,001,010,011,100,101,110,111(8个子网)因为2,4,8所以划分为8个,用3位。网络地址:主机号全0。广播地址:主机号全1。
2024-06-28 21:40:04
377
原创 Vim编辑器基本使用技巧详解
wq保存在命令模式下按下:(英文冒号)就进入了底线命令模式。【光标变到最底下,就可以输入一些底线命令了】底线命令模式可以输入单个或多个字符的命令,可用的命令非常多。在底线命令模式中,基本的命令有(已经省略了冒号):q 退出程序w 保存文件按ESC键可随时退出底线命令模式。
2024-06-28 00:41:19
572
原创 go version go: cannot find GOROOT directory
自从1.8版本开始,GOROOT、GOPATH有默认路径,不再需要手动配置,并且启动GO Moudle模式也不需要将代码写在GOPATH下面。默认配置以我自己为例如下。或者import "github.com/q1mi/hello"然后再go mod tidy也可以。,所以我们需要换一个PROXY,这里推荐使用。
2024-06-27 01:29:43
285
原创 ReentrantReadWriteLock
0 and w == 0 表示有读锁(之前有的),【读锁不能升级】,直接返回 false====从这里也能看出不能升级,也就是原先有了读锁还要尝试tryAcquire获取写锁。读-读能共存、读-写不能共存、写-写不能共存【读锁保护数据的 read() 方法,写锁保护数据的 write() 方法】不同线程间读写是互斥的。// 记录读锁线程自己的持有读锁的数量(重入次数),因为 state 高16位记录的是全局范围内所有的读线程获取读锁的总量。可以去申请读锁,其他线程拿不到锁了,因为读写不共存。
2024-06-25 23:44:31
505
原创 JUC线程池最佳实践
使用 Spring 内部线程池ThreadPoolTaskExecutor 时,一定要手动自定义线程池,配置合理的参数,不然会出现生产问题(一个请求创建一个线程)【如网络请求、文件读写等,可以采用异步操作的方式来处理】是不同的业务使用不同的线程池【父子任务用同一个线程池容易死锁】,重心优化。(线程数太大,增加上下文切换消耗)。【美团的线程池参数动态配置】(设置线程池名称前缀,有业务含义)【 guava 的。值的传递功能,解决异步执行时上下文传递的问题】线程池是可以复用的,一定不要频繁创建线程池。
2024-06-24 22:36:21
307
原创 WebSocket
WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输。HTTP是短连接(一次请求响应之后连接就断了,生命周期结束,需要重新建立连接)【请求响应模式】WebSocket是长连接(生命周期长)HTTP通信是单向的,基于请求响应模式WebSocket支持双向通信HTTP和WebSocket底层都是TCP连接。
2024-06-23 11:31:57
321
原创 LinkedBlockingQueue 原理
////注意,这种情况是take之前,队列已经满了,之前的所有生产者都等待呢。// 这里调用的是 notEmpty.signal() 而不是 notEmpty.signalAll() 是为了减少竞争。// 这里调用的是 notFull.signal() 而不是 notFull.signalAll() 是为了减少竞争。// 如果有多个线程进行出队, 第一个线程满足 c == capacity, 但后续线程 c < capacity。// 如果队列中只有一个空位时, 叫醒 put 线程。
2024-06-22 20:02:12
989
原创 CyclicBarrier改善CountDownLatch循环重入
线程数要和基数保持一致,否则可能时两个线task1完成。第二次循环线程池还有线程的话可以去竞争。:线程调用 await 方法通知 CyclicBarrier 本线程已经到达屏障【基数不为0不会向下进行】谁调用await就阻塞谁,这个能阻塞多个,countdownlatch只能阻塞一个。应用:可以实现多线程中,某个任务在等待其他线程执行完毕以后触发。跟CountDOwnLatch非常类似,也是计时结束执行。parties:代表多少个线程到达屏障开始触发线程任务。(屏障),用来进行线程协作,
2024-06-20 22:27:22
958
原创 Semaphroe + CountDown
让当前线程等待,必须 down 完初始化的数字才可以被唤醒,否则进入无限等待【计时(数)器走完】:表示释放许可,acquire() 和 release() 方法之间的代码为同步代码。synchronized 可以起到锁的作用,但某个时间段内,只能有一个线程允许执行。:fair 表示公平性,如果设为 true,下次执行的线程会是等待最久的线程。// 4. 释放许可。,线程都是不断再运行的,肯定不能让某一个线程结束。
2024-06-20 20:53:34
780
原创 有HTTP为什么还要RPC
RPC80年代诞生,HTTP90年代诞生。所以准确来说是有RPC为什么还需要HTTP。跨微服务的远程调用(RPC,即emoteroduceall)RPC的实现方式有很多,比如:基于Http协议基于Dubbo协议[ 都只是定义了不同消息格式的而已。RPC本身并不是一个具体的协议,而是一种(grpc这种具体实现才是协议)。可以]RPC长连接复用且有连接池。-----OpenFeign 进行远程调用不需要开发人员手动构造 HTTP 请求对象、设置请求参数等RPC,因为它。
2024-06-20 15:28:03
419
原创 java线程池讲解!核心参数
当一个线程空闲超过一定的时间(keepAliveTime)时,线程池会判断:如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉,所以线程池的所有任务完成后最终会收缩到 corePoolSize 大小【当线程数达到 corePoolSize 并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue 队列排队,直到有空闲的线程。----【会让核心线程一直运行】线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。线程池的线程都是非守护线程?
2024-06-13 23:30:11
894
原创 通过自定义线程池初步理解JAVA线程池
组件:线程池:存储可重用的线程(相当于消费者,不断获取任务来消费)阻塞队列:生产者消费者模式下平衡他们速度差异的组件 ----【1.生产者里线程迟迟没有提交任务,生产者需要等待,阻塞队列为等待位置。2.任务一下子特别多忙不过来,存入阻塞队列】main:生产者,源源不断产生线程实现:// 1. 任务队列// 2. 锁。保护阻塞队列,锁住头和尾,因为会有多个生产者消费者。// 3. 生产者条件变量。达到容量变量,阻塞,在条件变量等待// 4. 消费者条件变量。
2024-06-12 10:17:23
182
原创 RateLimiter实现令牌桶算法和漏桶算法
第三方工具类:disruptor(高性能的无阻塞的无锁队列)、guava--RateLimit(高性能的信号量的限流器)----【基础的类库】在 Guava 的中,并没有直接提供实现漏桶算法的方法,因为的设计就是基于令牌桶的。但是,如果我们想实现一个漏桶算法,我们需要自己编写代码来模拟水的流入和流出。
2024-06-11 21:56:41
537
原创 解析final原理
final 变量的赋值通过 putfield 指令来完成,在这条指令之后也会加入写屏障,保证在其它线程读到它的值时。//final保证不能读到两个值。第三种:【不加final都算是在堆中,Getstatic速度小于上面两种】5: bipush 20 // 将值直接放入栈中。之前的修改、赋值操作之后会同步到主内存中去(可见性)大于 short(短整型) 最大值会将其复制到类的。之前的指令不会重排序到后面去(有序性)其他线程访问 final 修饰的变量。,访问时从常量池获取。
2024-06-10 23:37:02
210
原创 什么是CAS?
CAS 并发原语体现在 Java 语言中就是 sun.misc.Unsafe 类的各个方法,调用 UnSafe 类中的 CAS 方法,JVM 会实现出 CAS 汇编指令,这是一种完全依赖于硬件的功能,实现了原子操作。,是由若干条指令组成 ,用于完成某个功能的一个过程,并且原语的执行必须是连续的,执行过程中不允许被中断,所以 CAS 是一条 CPU 的。执行的是循环操作,如果比较不成功一直在循环,最差的情况某个线程一直取到的值和预期值都不一样,就会无限循环导致饥饿,引出来 ABA 问题。
2024-06-09 18:08:23
975
原创 MySQL事务原理
MVCC 靠 隐藏字段 , undo log 版本链 , read view 实现的。原子性-undo log持久性-redo log一致性-undo log + redo log隔离性-锁 + MVCC。
2024-06-08 23:26:12
835
原创 volatile原理(内存屏障)
volatile场景 一个线程写,其他线程读的情况 double-check-lock时,synchronized同步代码块外共享变量的指令重排序问题 同步机制volatile 是 Java 虚拟机提供的轻量级的同步机制(三大特性) 保证可见性 不保证原子性 保证有序性(禁止指令重排) 性能:volatile 修饰的变量进行读操作与普通变量几乎没什么差别,但是写操作相对慢一些,因为需要在本地代码中插入很多内存屏障来保证指令不会发生乱序执行,但是开
2024-06-05 17:31:25
922
原创 单例设计模式+volatile讲解!
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。单例模式的主要有以下角色:单例类。只能创建一个实例的类访问类。使用单例类 【demo类】
2024-06-05 17:25:26
667
原创 swagger2显示错误解决:Could not render e, see the console.
同时可以根据environment去处配置要给那些开发环境设置swagger文档,底层会通过扫描配置文件中的active来判断当前的开发环境。环境符合则flag返回true,false则会显示不可用。出现这种情况就是swagger的配置类出了问题,在.enable()中传入了false。active: pro #dev(开发) #pro(生产)
2024-06-04 21:56:44
792
原创 多线程如何Debug!
首先打上断点,然后点击右键,点击Thread即可在控制台中查看到运行状态,Runnable会显示为Running,Blocker会显示为Monitor,只是idea显示idea显示的问题,不需要太在意。
2024-06-01 23:28:27
187
原创 MySQL事务讲解
update account set money = money - 1000 where name = '张三';事务是一组操作的集合,事务会把所有操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。update account set money = money - 1000 where name = '张三';select * from account where name = '张三';-- 设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效。
2024-05-31 22:40:35
386
原创 MySQL存储引擎介绍!
不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。服务层 第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。InnoDB 是一种兼顾高可靠性和高性能的通用存储引擎,在 MySQL 5.5 之后,InnoDB 是默认的 MySQL 引擎。在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。InnoDB: 如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含。
2024-05-30 23:17:31
517
原创 动态代理详解!
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生成,而动态代理代理类则是在Java运行时动态生成。动态代理又有JDK代理和CGLib代理两种。打个比方,高铁站这个原始对象(功能)卖高铁票,但要通过前台窗口这个代理类卖票。
2024-05-29 20:56:36
703
原创 MySQL索引失效场景以及索引设计原则
因为只要有一个没有索引,另外一个用不用索引都没有意义,都要进行全表扫描。联合索引最左匹配法则----【像like '%zz'一样,表中全是索引列可能走全扫描二级索引树,type = index, Using index覆盖索引】】--------- 注意:使用左模糊匹配(like "%xx")并不一定会走全表扫描,关键还是看数据表中的字段(【联合索引不适用于 or】 【必须都是索引列,【导致索引列的值发生变化,从而破坏了B+树索引的有序性】 【要控制索引的数量,索引并不是多多益善,
2024-05-27 20:27:14
880
原创 MySQL日志解析
undo log 为每条记录保存多份历史数据,MySQL 在执行快照读(普通 select 语句)的时候,会根据事务的 Read View 里的信息,顺着 undo log 的版本链找到满足其可见性的记录。:开启事务后,InnoDB 层更新记录前,首先要记录相应的 undo log,如果是更新操作,需要把被更新的列的旧值记下来,也就是要生成一条 undo log,undo log 会写入 Buffer Pool 中的 Undo 页面。:回放 binlog,并更新存储引擎中的数据。但 ROW 的缺点是。
2024-05-26 21:39:50
681
原创 八股文、JUC、JVM学习顺序
对于准备开始八股文、JUC、JVM的同学,由于之前我自己查这个都说的是没有要求,但当我学完之后发现,JVM应该放在JUC之前,因为在JUC中偶尔会出现JVM的内容,比如需要字节码方面的知识帮助理解JUC。所以,总的建议就是JUC在JVM之后,可以伴随着八股文一起进行,比如看到锁可以顺便把Mysql的全局锁、表锁、行锁、mvcc一起看了,联系起来。
2024-05-25 22:42:09
286
原创 Insert 语句是怎么加行级锁的?如何避免死锁
时间:当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。如果 where 条件带上了索引列,但是优化器最终扫描选择的是全表,而不是索引的话,我们可以使用。:主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。,其特点是只有在可能发生冲突时才加锁,从而减少了锁的数量,提高了系统整体性能。隐式锁就是在 Insert 过程中不加锁,只有在特殊情况下,才会将隐式锁。,这种机制称为隐式锁。【锁的状态是各个事务共享的,因为锁是加在索引上的】
2024-05-25 21:37:32
378
原创 MySQL行级锁-详解!
唯一索引等值查询:当查询的记录是「存在」的,在索引树上定位到这一条记录后,将该记录的索引中的 next-key lock 会退化成「记录锁」。当查询的记录是「不存在」的,在索引树找到第一条大于该查询记录的记录后,将该记录的索引中的 next-key lock 会退化成「间隙锁」。非唯一索引等值查询:当查询的记录「存在」时,由于不是唯一索引,所以肯定存在索引值相同的记录,于是非唯一索引等值查询的过程是一个扫描的过程,直到扫描到第一个不符合条件的二级索引记录就停止扫描,然后。
2024-05-24 23:21:16
1650
1
原创 常用Markdown语法
首先本人最常用的就是:(1)小圆点:减号 + 空格 + 内容(2)代码块: 三个` + 语言种类 + 内容(3)左竖线:大于号 + 空格 + 内容。可以自己设置颜色,在Typora的css文件中。(4)颜色:两个等号 + 内容 + 两个等号。
2024-05-24 15:13:28
321
原创 详解MVCC以及尽可能解决幻读的两种方案
第二个例子:对于当前读,如果事务开启后,并没有执行当前读,而是先快照读(导致有机可趁),然后这期间如果其他事务插入了一条记录,那么事务后续使用当前读进行查询的时候,就会发现两次查询的记录条目就不一样了,所以就发生幻读。针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。(3)要看隔离级别,RR肯定不能读。
2024-05-24 14:48:56
674
1
原创 MySQL锁都有什么?详解!
InnoDB的数据是基于索引组织的【行数据是基于聚集索引组织的】,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。因为在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的 Read View,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。那么有了「意向锁」,由于在对记录加独占锁前,先会加上表级别的意向独占锁,那么在加「独占表锁」时,直接查该表是否有意向独占锁,如果有就意味着表里已经有记录被加了独占锁,这样就不用去遍历表里的记录。
2024-05-24 14:47:36
394
原创 谷粒商场p75传过去的catId为null问题
只需要在src\views\modules\product\category.vue下的。通常,编辑方法应该接收一个参数,该参数包含了你点击的节点的数据,其中应该包含。然后,你可以从这个参数中获取正确的。edit(data) {……需要在编辑方法中传递正确的。
2024-05-24 14:46:05
282
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人