AQS原理解析 使用者继承并重写指定的方法。将 AQS 组合在自定义同步组件的实现中,并调用其模板方法,而这些模板方法会调用使用者重写的方法。//独占方式。尝试获取资源,成功则返回true,失败则返回false。//独占方式。尝试释放资源,成功则返回true,失败则返回false。//共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。//共享方式。尝试释放资源,成功则返回true,失败则返回false。//该线程是否正在独占资源。
Springboot启动https安全协议 https协议是http+ssl协议,由于http协议是明文传输的超文本协议,在数据传输过程中,容易被”截胡“,进而导致数据泄露,在重要网站输入用户账户密码时是极为危险的情况。于是Https协议便诞生了,ssl是一个证书,其中会包含一对证书。
当前读和快照读 当前读,也被称为锁定读,它会对读取的行记录加锁,以保证在事务进行期间,读取的数据不会被其他事务修改。这种读操作会实时反映数据库的最新状态,因此被称为“当前”读。在MySQL中,使用以下SQL语句会触发当前读:这些语句会在读取数据的同时,对相应的行记录加上锁,以防止其他事务对其进行修改。这种读方式通常用于需要保证数据一致性的场景,比如金融交易等。示例代码当前读的底层原理:当前读,也被称为锁定读,它会对读取的行记录加锁,以保证在事务进行期间,读取的数据不会被其他事务修改。
图遍历算法模板 深度优先遍历用递归+记忆化网格结构的 DFS 与二叉树的 DFS 最大的不同之处在于,遍历中可能遇到遍历过的结点。这是因为,网格结构本质上是一个「图」,我们可以把每个格子看成图中的结点,每个结点有向上下左右的四条边。在图中遍历时,自然可能遇到重复遍历结点。这时候,DFS 可能会不停地「兜圈子」,永远停不下来,如下图所示:如何避免这样的重复遍历呢?答案是标记已经遍历过的格子。以岛屿问题为例,我们需要在所有值为 1 的陆地格子上做 DFS 遍历。
类加载之双亲委派 双亲委派(Parent Delegation)是 Java 类加载机制中的一个重要概念。它指的是当一个类加载器(ClassLoader)需要加载某个类时,它会首先将加载请求委派给它的父类加载器,依次递归,直到顶层的启动类加载器(Bootstrap ClassLoader)。只有在父类加载器无法加载该类时,才会由子类加载器尝试加载。这种机制的优势在于确保了类的唯一性避免了同一个类被多个类加载器加载导致的类重复问题。
ThreadLocal源码分析&内存泄漏详解 ThreadLocal是多线程中解决线程安全的一个类,它会为每一个线程都分配一个独立的线程副本从而解决了变量并发访问冲突的问题。ThreadLocal实现了线程内的资源共享。例如:使用JDBC操作数据库时,会将每一个线程的Connection放入各自的ThreadLocal中,从而保证每个线程都在各自的Connection上进行数据库的操作,避免了A线程关闭B线程的连接。可以说在ThreadLocalMap中存储Key是定义的ThreadLocal对象,Value是实际设置的值。!
创建单例模式的方法 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
Springboot项目集成Skywalking链路追踪系统 Springboot与Skywalking的集成过程总的来说比较简单,第一步就是配置Skywalking,第二部配置Java Agent即可此后可以使用Skywalking来分析哪个接口的执行速度比较慢,由此可以看到SQL的具体执行时间,可以定位到哪个sql出现了问题,有助于解决mysql的慢查询的问题。
Redis底层数据结构-Dict Redis的键与值的映射关系是通过Dict来实现的。Dict是由三部分组成,分别是哈希表(DictHashTable),哈希节点(DictEntry),字典(Dict)哈希表结构如下图所示:由于会发生哈希冲突,所以entry个数可能会大于sizesize总是2的n次方哈希节点的结构如下图所示:当我们向Dict添加键值对时,Redis首先根据key计算出hash值(h),然后利用h&sizemask(其实就是h对数组长度取余)计算元素应该存储到数组中哪个索引位置。
Redis底层数据结构-IntSet 其实数组本身只是一个指针,指向起始元素的地址,intset并不依赖于C语言提供的数组相关函数,所有增删改查都是自己来做的。,在本例子中升级编码为INTSET_ENC_INT32,每个整数占4字节,并按照新的编码方式以及元素个数扩容数组.IntSet是Redis中set集合的一种实现方式,基于整数数组来实现,并具备长度可变,有序等特征。由此,对这个数组的操作和大小并不是像表面看到的一样,而是由encoding来决定 的。倒序依次(先调整20,10,5)将数组中的元素拷贝到扩容后的正确位置。
Redis底层数据库之SDS 由于len是uint8_t类型,最大值为254,所以字符串最大长度为254(因为char buf[]仍然是C语言的字符串,会有一个结束符)Redis中保存的Key是字符串,value往往是字符串或者字符串的集合。可见字符串是redis中最常用的一种数据结构。假如在该字符串追加一段”,AMY“,那么会去申请新空间(alloc为申请的存放字符的空间,不包含结束字符)所以Redis构建了一种新的字符串结构,成为简单动态字符串,简称SDS。flags:表示不同的结构体类型。uint8_t:表示无符号整型。
Springboot启动https安全协议(JDK生成SSL证书) https协议是http+ssl协议,由于http协议是明文传输的超文本协议,在数据传输过程中,容易被”截胡“,进而导致数据泄露,在重要网站输入用户账户密码时是极为危险的情况。于是Https协议便诞生了,ssl是一个证书,其中会包含一对证书。
MYSQL百万数据查询优化 在查询第100000条记录之后的10条时,耗费时间:0.227s在查询第200000条记录之后的10条时,耗费时间:0.251s在查询第500000条记录之后的10条时,耗费时间:0.916s在查询第800000条记录之后的10条时,耗费时间:1.639s在查询第1000000条记录之后的10条时,耗费时间:2.038s以上叫做深度分页,即查询偏移量过大的场景,这会导致查询性能较低。
LeetCode 61. 旋转链表 其实像例1中,链表长度length为5,当k为5,10,15时,链表其实是没有变化的,当k为6,11,16时也只是相当于旋转了一次,所以旋转得次数其实是k%length。解题思路:本题中比较简单想法就是使用递归做法,每做一次递归使得k-1,将尾节点接到首节点左边,但是这样做当K特别大时会出现栈溢出的情况。输入:head = [1,2,3,4,5], k = 2。输入:head = [0,1,2], k = 4。链表中节点的数目在范围 [0, 500] 内。输出:[4,5,1,2,3]输出:[2,0,1]
LeetCode215. 数组中的第K个最大元素 为了保证稳定性,随机获取集合中的一个元素pivot进行排序,所以我们可以判断比该pivot元素小的元素个数(low.size()),比该pivot元素大的元素个数(above.size()),以及和该pivot元素相等的元素个数(equal.size())请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。输入: [3,2,3,1,2,4,5,5,6], k = 4。输入: [3,2,1,5,6,4], k = 2。此时我们所知道的是要查找第K大的元素。
LeetCode162. 寻找峰值 这是因为nums[mid-1]>nums[mid],同时左边界为无穷小。此时在nums[0]~nums[mid]中必有峰值元素。就和现实中爬山一样,在nums[mid]端向左爬,是上山,但最终会下到山底,所以必然会有一个山峰。如果nums[mid-1]>nums[mid]那么在左半端必有峰值元素,右半端同理。你可以假设 nums[-1] = nums[n] = -∞。输入:nums = [1,2,1,3,5,6,4]解释:你的函数可以返回索引 1,其峰值元素为 2;输入:nums = [1,2,3,1]