自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

小辉的编程学习记录

Java后端为主,前端,运维等等全栈选手

  • 博客(99)
  • 收藏
  • 关注

原创 适配器模式

比如充电,插座的电压为 220V(被适配者),手机(客户端)通过充电器(适配器)将插座的电压降到 5 V(目标接口)传输电压给手机(客户端)。定义一个多个方法的接口,使用抽象父类来实现该接口并实现接口中的所有方法,子类要使用的话使用覆盖其中的一个方法就可以了。因为类适配器需要适配器去继承被适配者,不符合合成复用原则,使用对象适配器可以解决这一问题,将被适配者聚合到适配器中。因为只在上述的类加载器的基础上修改了适配器,所以只贴出适配器的与客户端的代码,其余与类加载器一致。

2024-07-20 14:26:01 533

原创 Redis的过期删除策略与内存淘汰机制

定期删除:Redis 默认是一秒定期删除 10 次,这个可以在配置文件中设置,每一次执行删除会从过期字典中取出 20 个key,判断其中的Key 是否达到过期,是的话就删除,如果本轮检查中过期的 key 超过 5 个(4/20),也就是「过期的key」 占「总得key」的比例超过 25%,总会继续从过期字典中取出 key 进行删除。内存淘汰机制一共为八种,主要分为两种类型,一种是「不删除数据的淘汰机制」,另一种是「删除数据的内存淘汰机制」。Redis 采用惰性删除与定期删除的策略来保证过期键值的删除。

2024-07-18 14:00:00 471

原创 线程池参数策略

线程池维护一组核心线程池数的线程,当有超过该线程数的任务时,会被放在堵塞队列中等待,如果任务太多,堵塞队列也满了的话,会判断当前的线程数是否小于最大的线程数,是的话就会继续创建线程。CPU密集型:计算机应用的类型,为了可以充分的发挥CPU,线程池的数量一般为 CPU 的核的个数或倍数。当创建到等于最大线程池数的线程之后,如果还有任务的出现,并且把阻塞队列也满了,此时就会使用拒绝策略。使用超过核心线程数的存放时间,一般短的任务可以设置较短的存活时间,长的任务设置较长的存放时间。

2024-07-16 14:23:58 391

原创 Java所有的锁

又名排他锁,互斥锁,只有一个线程可以获取,一般为写锁,当有一个线程获取到独享锁,其他线程都不可以获取锁,获取锁的线程可以写入数据,修改数据等等,直到该线程释放,其余线程才可以获取锁。又名读锁,当一个线程获取到该共享锁时,其他线程也可以获取共享锁,但是不能获取其他的锁,多个线程可以获取,ReentrantReadWriteLock 中的读锁就是共享锁, 也一般为读锁。非公平锁的效率比较快,因为如果是公平锁,每一次获取锁就要唤醒一个线程,CPU 切换线程状态是比较耗时的,会消耗 CPU 的资源。

2024-07-16 11:14:10 483

原创 设计模式的七项原则

类实现接口上,遵循最少接口原则,比如接口A要五个方法,实现类A是需要用来其中的三个方法,实现类B只需要用到其中的两个方法,那么就可以把接口A拆分为接口A(只包含类A的三种方法)+接口B(只包含类B的两种方法)。一个类负责一个职责,不可以让一个类负责多项职责,这样会导致类的难管理,但是也不要把一个类切分的太细。当我们需要新增功能时,尽量的只去增加代码,而不是修改代码,提高代码的可用性,可靠性,安全性。细节依赖于抽象,底层依赖与高层,高层依赖于抽象,以抽象为高层,更好的进行类之间的管理。

2024-07-12 11:44:48 316

原创 代理模式(静态代理,动态代理,cglib代理)

代理模式属于结构型的模式,通过代理对象来访问目标对象,即可以扩展目标对象的功能,比如日志记录,或者是安全检查,我们常用的AOP面向切面编程是属于一种代理模式。使用的代理工厂实现methodIntecetor,重写 intecetor方法就可以了。代理模式的形式:静态代理,动态代理(JDK 代理),cglib代理(基于内存实现)代理对象与目标对象都要实现同一个接口或者父类,客户端通过代理对象来访问目标对象。又称为 JDK 代理,通过JDK 反射的包来实现。cglib代理是可以不急于抽象父类或者抽象接口。

2024-07-12 11:44:14 618 1

原创 建造者模式

*** 产品**/@Data/*** 抽象建造者**//*** 具体建造者:普通房子**/@OverrideSystem.out.println(" 普通房子打地基 5 米 ");@OverrideSystem.out.println(" 普通房子砌墙 10cm ");@OverrideSystem.out.println(" 普通房子封顶 ");/*** 具体建造者:高楼**/@Override。

2024-07-07 13:28:28 902

原创 单例模式之静态内部类与枚举类

推荐使用创建单例模式有:双重检查锁,静态内部类,枚举类。如果确保对象一定会被使用,那么使用饿汉式的创建方式也可以。

2024-07-07 12:07:59 499

原创 单例模式之懒汉式

是的,但是也出现了线程不安全的问题,比如有多个线程进入 if (singleton == null) 那么是不是会有多个线程进行创建对象。虽然解决了线程安全问题,但是性能太差了,每一次调用实例都需要进入同步方法,其实我们创建实例的时候保持同步就可以了。我们只需要在加锁的代码块中再进行一次空判断,就可以很好的解决并发问题了,当一个线程进入的时候,先判断是否为空,为空才创建对象,不为空直接返回。懒汉式是符合懒加载的模式,但是会存在线程并发的问题发生,所以还需要一种解决线程并发的机制,比如:加锁等。

2024-07-06 15:19:05 880

原创 单例模式之饿汉式

单例模式是一种创建性的设计模式,主要是保证一个类只能有一个实例。全局中保证一个实例的使用。缺点:不符合懒加载情况,在不使用该实例的时候会造成内存浪费。优点:提前实例化,不存在线程并发等问题。单例模式饿汉式主要的构成是如下。

2024-07-06 15:17:27 594

原创 缓存穿透与缓存雪崩的解决方案

缓存雪崩:大量缓存在一起失效,导致大量请求到数据库上,从而导致数据库宕机。因为本来请求是请求到缓存上的,但是当缓存失效的时候,大量的请求都落在数据库上。缓存穿透:数据库中没有这条数据,缓存中也没有这条数据,所以导致请求一直在请求,但是没有数据返回。当大量的请求到数据库中,从而导致宕机。接下来我们采用设置不同的过期时间来解决缓存雪崩的问题,以及返回空值来解决缓存穿透的问题。具体可以看一下代码注释。

2024-07-04 10:15:17 291

原创 抽象工厂模式

*** 抽象产品:ProductA*/void use();/*** 具体产品 ProductA1**/@Override/*** 具体产品 ProductA2**/@Override/*** 抽象产品:ProductB*/void use();/*** 具体产品 ProductB1**/@Override/*** 具体产品 ProductB2**/@Override/*** 抽象工厂**//*** 具体工厂 1**/

2024-07-04 10:14:27 412

原创 工厂方法模式

*** 产品**/void use();/*** 实现类**/@Override/** 抽象父类**//** 具体的子类工厂**/@Override。

2024-07-03 17:00:57 467

原创 工厂模式之简单工厂模式

System.out.println("Person , 我是一个人");@OverrideSystem.out.println("Student, 我是一名学生");@OverrideSystem.out.println("Man, 我是一名男人");@OverrideSystem.out.println("Lady,我是一名女生");}else{

2024-07-03 16:59:57 603

原创 策略模式实现

Service@Resource@Override//校验参数//修改状态值if (result!= 0){@Service@Resource@Override//校验参数//修改状态值if (result!= 0){定义一组策略(通过一个接口+多个实现类),为了减少 if - else 的时候,使用 map + 函数式编程存储策略方法,并且进行初始化。

2024-06-25 12:44:00 414

原创 Redis GEO 实现附近的人

Override//创建距离//创建参数//进行计算//遍历数据这样使用 GEO 实现查询附近的人的功能就实现了。首先要先上传所有用户的经度与纬度,然后使用 GEO 的命令,获取当前的登录用户的 id,以及所有用户的 id,用当前用户与计算用户进行距离的计算,得到距离 distance 值。

2024-06-25 12:43:15 280

原创 Java所有的锁

在尝试获取锁失败后,线程不会阻塞,通过自旋尝试继续获取锁,等待锁的释放。线程到了之后先尝试获取锁,获取不到再排队,优点是:提高了 CPU 的吞吐效率,减少了 CPU 切换线程状态的次数。缺点:线程可能饿死。非公平锁的效率比较快,因为如果是公平锁,每一次获取锁就要唤醒一个线程,CPU 切换线程状态是比较耗时的,会消耗 CPU 的资源。非公平锁,线程一到先获取锁,而不是先堵塞,这样有几率减少 CPU 的切换线程状态的次数,减少 CPU 的压力。反之,在外层获取锁的线程,不可在内层中继续获取相同对象的锁。

2024-06-14 10:49:33 392 1

原创 JUC基础概念

JUC 是 Java.utils.concurrent 包内的类,是为了开发者可以在多线程的情况下减少竞争条件和防止死锁而出现的。

2024-06-14 10:48:44 464

原创 MySQL索引面试题(高频)

今天来讲一讲 MySQL 索引的高频面试题。主要是针对前一篇文章MySQL索引入门(一文搞定)进行查漏补缺,建议大家看完前一篇再看这一篇。总的来说,我们只要符合索引的优缺点就可以知道索引该如何使用拉。优点:快速查询,缺点:浪费空间,影响数据更新性能。我是小辉,正在应届找工作中,第二版修改于20240612。

2024-06-12 13:43:43 1093

原创 索引的基础知识(入门级)

MySQL 的索引是面试的高频考点也是我们在日常开发中用于优化 SQL 语句性能的神器。今天跟大家讲一讲 MySQL 的索引入门篇章。对索引的知识有大概的了解…索引就是一种可以快速查询的数据结构,在MySQL中担任着提高查询性能的角色。打个比方:一本书的目录,通过目录我们可以快速找到这本书的第一章,第二章分别在第几页,这个目录相当于索引总的来说,索引就是一个可以实现快速查询的数据结构,优点是查询快,缺点更新慢,浪费空间,Innodb 默认的索引数据结构是B+树,索引可以按照多种特性进行分类。

2024-06-12 13:42:43 594

原创 HashMap源码解析

因此 n - 1 就是二进制低位全是1,跟 hashCode 相与的话会将左边的哈希值的高位全抹掉,剩下的就是余数了,因此相当于 HashCode % n, 两者的结果是一样的,但使用 HashCode & (n - 1)是位运算,执行在硬件层,效率比直接求余要高。扩容机制:HashMap 的默认容量为 16 ,负载因子为 0.75,当集合中的元素超过容量与负载因子的乘积时,会引发扩容机制。树化的过程,两个条件:1.hashmap 的容量要大于等于 64 并且 链表的长度要大于等于 8 ,才能实现树化。

2024-06-11 16:46:39 592

原创 ArrayList源码解析

ArrayList:是基于数组实现的集合列表,它被称为动态数组,因为相比与数组的固定大小,ArrayList 当添加元素时,添加的元素数量大于数组的容量的话就会触发扩容机制。ArrayList 是线程不安全的,如果要实现线程安全,可以使用 CopyOnWriteArrayList,或者用 Collections 工具类封装。每次通过右移的方法扩容 1.5 倍,最后将旧数组的元素复制到新数组中。数组的移除是通过覆盖的方式完成,将该元素后面的值往前覆盖。很简单,直接根据下标设置数组的元素。

2024-06-11 14:59:09 399

原创 Java基础-一文一答系列

在没有重写equals方法的时候,两者是一样的,都是在比较元素的内存地址是否相同,但是如果我们重写了equals方法,在比较对象的时候,就可以将对象原本比较内存地址的改为对象之间的逻辑内存的对比。答:BigDecimal,相比于 Double ,Folat,BigDecimal 的精度大,准确度高,优点是准确率高,缺点是在数据比较大精度的时候计算比较慢。这是一种规范,例如我们在使用 HashMap的时候,也是先计算元素的 HashCode,相同的话再进行 equals 的比较。大家好,我是小辉,持续分享。

2024-06-09 14:50:08 795

原创 Java 基础知识点

修饰的类为抽象类,里面可以定义抽象方法,普通方法,局部变量,如果子类不是抽象类继承抽象父类需要重写抽象父类的方法。

2024-06-08 16:25:52 711

原创 插入排序(排序算法)

插入排序,类似于扑克牌的玩法一样,在有序的数组中,扫描无序的数组,逐一的将元素插入到有序的数组中。我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。

2024-06-06 17:50:20 366

原创 Java 基础面试题

使用时通过创建一个对象来调用类中的方法,创建一个一个类似于模块化的结构,每个类各司其职,便于管理与维护,也起到代码复用的效果。抽象类:用 abstract 修饰的类为抽象类,里面可以定义抽象方法,普通方法,局部变量,如果子类不是抽象类继承抽象父类需要重写抽象父类的方法。第二种是运行时多态,对象引用的具体类型在运行时才确定,通过子类继承父类并重写父类的方法,然后使用父类的引用指向子类的对象实现。程序在运行时的时候,通过反射来获取类信息,用类来调用方法与属性,或者通过反射获取对象,用对象来调用方法与属性。

2024-06-06 15:29:52 627

原创 选题排序(十大排序算法)

选择排序:每一次找出数组中最小的元素,并放在对应的索引位置上。一般为两位for循环,内层for循环不断的缩减。不稳定,时间复杂度为 O(n²)我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。

2024-06-04 15:15:40 322

原创 Spring IOC 与 AOP 基础原理

Bean 是存储在IOC 容器中的对象。

2024-06-04 13:35:05 684

原创 HashMap扩容机制

触发条件:HashMap 的默认容量为 16 ,负载因子为 0.75,当集合中的元素超过容量与负载因子的乘积时,会引发扩容机制。我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。​ 如果红黑树的值小于 6 ,就会退化成链表。

2024-05-30 16:10:35 766

原创 冒泡排序(经典)

2.i 的初始化为 0,是j的初始化也为 0,注意 j 的终止条件为:j < arr.length - i - 1,是为了防止越界。1.优化的 flag 是为了减少排序次数,如果在一次比较中都没有交换数据,那么这个数组就是有序的。总共由两次循环,外层循环为总共需要比较多少次,一般全部无序的数组,需要比较该数组的长度的值。内层循环,每一次比较需要比较多少次,每一次都比上一次减少一次的次数。我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。相邻的两个元素的比较,每次选出一个最大值。

2024-05-30 10:59:43 215

原创 移除链表元素

而链表的移除,只需改变改节点的前一个节点的取向指向改节点的下一个节点就可以了。代码:pre.next = cur.next;在解题的过程中,还存在一个问题,如果要删除头指针呢?头指针没有前一个节点该如何删除呢?我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。不创建虚拟头指针,就是需要对头指针进行一次单独的处理。还记得数组的移除元素吗?是使用双指针的不断覆盖完成。此时有创建虚拟头指针的方法与不创建虚拟头指针的方法。给你一个链表的头节点。时间复杂度为O(n)时间复杂度为O(n)

2024-05-29 10:23:33 380

原创 单链表,双向链表,循环链表

如上图所示,链表是由多个节点组成,节点由数据域与指针域组成,数据域用于存储数据,指针域指着下一个节点,其中第一个节点为头节点,倒数第二个节点的指针域指向空指针。链表的查询的性能较慢,每一次查询都需要从头指针出发,一个节点连着下一个节点,而增删改的时候只需要修改一个节点的指针。链表的底层内存不是连续的内存空间,是分散的内存块,一个块的指针连着下一个块。双向链表想较与单链表,多了一个prev指针域,用于指向前一个节点。当下是找工作ing,欢迎关注,持续分享。链表分为单链表,双向链表,循环链表。

2024-05-29 10:21:52 389

原创 螺旋矩阵(算法题)

我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。终点:**循环不变量,**每一次循环遵循左闭右开的原则。所有元素,且元素按顺时针顺序螺旋排列的。

2024-05-28 12:50:32 240

原创 有序数组的平方

时 result[index–] = nums[right] * nums[right];时 result[index–] = nums[left] * nums[left];因为有负数的存在,所以最大值一定是在最左边或者最右边,一定不在中间。我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。逐一的找出最大值,插入到result的最右边。定义最左边的指针与最右边的指针,逐一找出最大值。依旧是双指针,逐一找出最大值。初始化一个result数组。组成的新数组,要求也按。

2024-05-28 12:47:59 356

原创 移除元素(算法题)

示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。快慢指针,慢指针对应着返回的结果,快指针不断的向前寻找正确的值。正确的值就是不等于val的,说起来比较绕口,我们来看看代码。给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。元素的顺序可以改变。看代码中,快指针一步一步的向前搜索,慢指针用于锁定正确的值。

2024-05-27 19:41:43 331

原创 长度最长的子数组

我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。,并返回其长度**。**如果不存在符合条件的子数组,返回。依旧是双指针,此次我们也可以称为滑动窗口。找出该数组中满足其总和大于等于。个正整数的数组和一个正整数。//滑动,左指针向前。

2024-05-27 19:38:16 392

原创 二分查找(经典)

使用二分查找法,要注意循环不变量,当 right = nums.length - 1 时,一开始的范围为左闭右闭[left,right],那么你在循环的条件为while(left <= right)。当 number [middle] > target 时 right = middle - 1;遵循上方的左闭右闭原则。我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。因为left = right 是有意义的。第一从一个升序的整数数组中,找到目标值,,如果目标值存在返回下标,否则返回。

2024-05-26 14:16:50 425

原创 数组的理论知识

因为数组的内存空间是固定的,会造成内存不足或浪费的情况。而ArrayList是动态数组,它的大小会随着数组存储的元素大小而变化而且ArrayList还可以存储对象。,O(n),因为数组只可以覆盖,不可直接修改,比如我们删除 arr[1],那么之后的元素逐一的往前移动,此时 arr[1] = J,arr[2] = E。在Java中,数组我的经常使用的是动态数组ArrayList用于存储相同对象类型的数据。为什么有数组了,还要有ArrayList这种动态数组呢?数组的查询效率是比较快的,达到O(1)。

2024-05-26 14:15:54 326

原创 JVM垃圾回收机制

垃圾回收算法(Garbar Collector) 又称为分代算法,没有最好的算法,只有合适的算法,在合适的空间使用合适的算法。时间效率:复制算法 > 标记清除算法 > 标记整理压缩算法 (时间复杂度)内存整齐度:复制算法 > 标记整理 > 标记清除内存利用率: 标记整理 > 标记清除 > 复制年轻代:存活率低,使用复制算法老年代:区域大,存活率高,使用标记清除,标记整理我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。

2024-05-14 09:33:58 934

原创 JVM内存结构

在线程数大于 CPU 数的情况下,会存在线程切换,程序计数器会记下线程即将执行的操作,这样执行线程切换的话就知道下一步要执行什么,比如顺序执行,选择,循坏,异常处理。元空间又名方法区,主要存储静态变量,动态变量,常量,类信息(class模板,构造方法,接口定义),运行时常量池(字符串常量池)。操作数栈主要作为方法调用的中转站使用,用于存放方法执行过程中产生的**中间计算结果,**比如中间计算产生的临时变量。:程序计数器(PC寄存器),虚拟机栈,本地方法栈随着线程的产生而产生,随着线程的消失而消失。

2024-05-13 17:01:23 909

空空如也

空空如也

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

TA关注的人

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