自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 使用位图存储发券预约方式、分库分表分析

使用jason字符串将所有的预约模式进行存储在预约模式较少的情况下是可行的,但是涉及到序列化与反序列化,这是一部分开销,同时如果预约模式较多,那么需要将jason字符串反序列化为一个list集合,再拿当前传递参数的预约方式遍历的与list集合中的字符串进行对比,这样看来,开销不小。构建主键索引为userID+优惠券ID,因为查询的时候通过用户id与优惠券id就能唯一定义一行数据,并且可能涉及根据用户id查询对应的优惠券信息,所以用户id会放在索引创建的最左侧以满足最左前缀法则。

2025-07-16 15:02:35 725

原创 Mysql中存储引擎、索引、sql调优、锁、innodb引擎架构、MVCC多版本并发控制总结

行锁是在Mysql中粒度最细的锁,只有innodb引擎支持行级锁,行级锁可以分为行锁、间隙锁、临建锁。innodb引擎通过索引来构建数据内容,行锁只会锁住对于的索引,而不会对数据行row进行加锁。间隙锁会对索引之间的间隙进行加锁,也可以看作是对当前加锁索引的行row的间隙进行加锁,防止对行的间隙进行insert来避免幻读。临建锁是行锁于间隙锁的结合。事务是指一系列的数据库操作需要按照操作顺序原子性的完成,这个过程称为一个事务。

2025-07-15 21:46:59 247

原创 八股文——java基础:java枚举类

如果想要使用参数,那么就需要使用构造器去初始化参数。并且定义的参数必须使用private final来进行修饰。枚举类就是使用enum修饰的类,这部分类可以只写枚举,也可以为每个枚举添加对应的参数,比如。enum还有对应的enumSet和enumMap。枚举类中也可以有对应的函数方法。

2025-07-15 11:51:06 108

原创 redis数据结构和数据类型

dict的数据结构包含两张dictht表,记为ht(0)与ht(1),ht(0)用于存储当前数据,ht(1)用于rehash辅助来扩容与收缩。ht(0)与ht(1)会反复翻转,来实现扩容与收缩。扩容与收缩都是根据负载因子来判断的,最终都会找到离size最近的2^n作为新的存储容量。最后需要了解一个细节,rehash不是一次性转移整张表,而是批量处理部分数据内容,因为数据量大的情况下,处理时间会很长。

2025-07-11 20:47:56 748

原创 用户查询优惠券之缓存击穿

假设在一个商品秒杀活动场景下,商品ID123正在被秒杀,所有用户访问同一个key:product:123:info,为了减缓高频请求对这一个key的访问,可以将这个热key分片为100个子key,即product:123:info:shard0 ~ product:123:info:shard99,每条子key的内容都是一致的,无论请求访问哪条key的内容,结果都是相同。缓存击穿指的是某个热点key突然失效,比如说过期了,导致大量请求打到缓存,缓存不存在就去访问数据库,导致数据库压力暴增,甚至崩溃。

2025-07-09 19:55:06 762

原创 动态规划算法总结(未完)

最近在学习回溯和动态规划,感觉都挺头疼的,所以写篇总结合计,方便后续复习。

2025-07-09 13:12:08 278

原创 基于模板设计模式开发优惠券推送功能以及对过期优惠卷进行定时清理

通过上述DTO可以使得不同功能模块找到自己的实现方式(比如立即发送和延时发送就是通过判别DTO中delayTime是否为null,再比如通过Topic使得不同消费者只监听自己的内容)。通过两个事件类对两个功能模块所需属性做了区分,实质上最终传递的内容就是对应的事件。

2025-07-08 22:06:45 631

原创 开发项目时遇到的横向越权、行锁表锁与事务的关联与区别、超卖问题

首先需要明确,乐观锁可以是锁,也可以是一种思想。乐观锁的思想是,仅在非读操作的情况下进行检测加锁。也就是” 先不加锁,假设不会发生冲突;在写入前检测是否有冲突,若检测到冲突则重试或报错 “对应的悲观锁思想就是在操作之前进行上锁。比如在解决超卖问题,读写分离时可以新建一个version列:进行读:读出当前version进行写:判断写时的version是否是读时的version,如果不是,则重试或者报错。

2025-07-06 19:39:08 630

原创 八股文——JAVA基础:什么是反射?反射的优点和缺点都有哪些?反射的原理是什么?

简单来说,反射是一种可以让jvm在动态运行时拿到类的信息的一种方法。在编程时可以通过类对象来获取该类中基本信息,包括类方法、继承关系等。缺点在于安全性不足,因为使用反射可以绕过java的语言限制,比如可以拿到类中private私有的内容。反射的最大优势就在于反射是框架编写的基石,比如使用的spring框架、AOP面向切面编程等都是使用到了反射。反射的优点在于使得代码的编写更加灵活,比如配置文件的加载,只需要在配置文件中进行修改,而不需要修改代码。

2025-06-30 22:21:25 95

原创 八股文——什么是泛型?泛型如何使用

因为在jdk5版本之前,如List的使用没有泛型,如果添加的过程添加了两个不同类,编译时不会报错,而运行时会出现类转换异常,但是在使用了泛型之后,将报错提前到了编译时期,从而从根本上避免了类转换异常。泛型类比如mybatis plus中的IserviceImpl,通过泛型来标记对应实现类对应的类,泛型接口也可以参考MP中的Iservice,仍然通过泛型来标记对应实现的接口,泛型的应用类别分为泛型类、泛型接口、泛型方法。使用泛型可以增强代码的可读性和稳定性。2.工具类的实现,比如实现不同类的拼接。

2025-06-30 21:47:02 217

原创 八股文——JAVA基础:异常处理需要注意哪些

其次是明确非受检异常与受检异常,对受检异常进行捕获处理,而非受检异常最好在根源处进行处理,比如逻辑错误就去处理逻辑的错误,而不是进行 异常处理。首先是不要只捕获不处理,这样只是绕过报错,而没有起到真正处理的效果。除此之外,最好适配多个catch块来精准处理捕获的异常。还有就是使用业务自定义异常,调用更加清晰。

2025-06-30 21:08:55 100

原创 try-catch-finally 如何使用?

try用于捕获代码块的异常,catch用于处理try捕获的可能出现的异常,finally用于善后,比如在try catch中return之前有需要做的事,可以放进finally中。一个try可以有0个到多个catch块,如果没有catch块,那么finally块就必须要有,如果有catch块,finally块是非必须的。finally是否一定会执行?在非极端条件下,finally都会正常执行,除非虚拟机崩溃,线程被杀死finally无法继续执行。finally的一些应用:

2025-06-30 20:27:01 130

原创 JAVA八股文:异常有哪些种类,可以举几个例子吗?Throwable类有哪些常见方法?

Checked 异常通常表示“外部环境或 IO 操作”这类有可能因外部条件(文件不存在、网络中断、权限不足等)而失败的场景。的,Java 通过编译期强制你去“面对”这些错误——要么捕获,要么往上抛,让调用链上的某一层来决定如何恢复或提示用户。(文件、网络、数据库、线程等待等),在这些操作中失败是常态,而不是程序 bug,需要业务层去合理应对。,调用者一眼就能知道“这个方法存在读写失败的风险,需要处理或传递异常”,有助于写出更健壮的程序。出去,让调用者去处理(声明式),要么在方法内部用。

2025-06-30 20:04:00 356

原创 八股文——JAVA基础:常量折叠是什么?

常量折叠是jvm在底层进行常量的基本运算,比如。

2025-06-30 19:38:03 112

原创 八股文——JAVA基础:String s1 = new String(“abc“);这句话创建了几个字符串对象?

需要记住,常量池只会节省字面量(非new出对象时)的内存,因为多个字面量共享同一个常量池内容(常量池实质上是基于哈希表的索引)。如果没有“abc”这个字符串对象,那么会在堆中创建一个对象实例,并且在常量池中创建该实例的索引。如果已有"abc"这个字符串对象,那么常量池中不会再创建,只会在堆中创建一个对象。这段代码创建一个或两个对象。

2025-06-29 22:34:13 132

原创 字符串常量池是什么?

如果直接使用String s = "hello",那么hello这个字符串就会被创建在字符串常量池中,如果再创建一个String s2 = "hello",那么s与s2拥有相同的地址,因为"hello"是被存放再常量池中的。如果使用new来创建,对应创建的是一个对象,不同对象的地址不同,==比较的是地址,所以两个内容是不同的。这个常量池的思想与Integer的缓存区类似,不但相同。

2025-06-29 22:25:28 122

原创 八股文——JAVA基础:字符串拼接用“+” 还是 StringBuilder?

操作符 + 底层使用的是StringBuilder来进行实现的,+ 用于拼接的缺陷在于使用StringBuilder,本身线程不安全,其次在循环中使用 + 来拼接,会导致重复创建StringBuilder对象,导致空间的浪费。而在循环中使用StringBuilder就不会出现这个问题。java中仅有两个操作符的重载就是用于字符串的拼接操作的:+与+=

2025-06-29 22:12:54 102

原创 String字符串与StringBuffer、StringBuilder的区别以及String的不可变性是什么

其中String与StringBuffer是线程安全的,StringBuilder是线程不安全的,因为StringBuilder是直接修改字符串内部,而String与StringBuffer是不会修改内部内容,而是new一个新的对象,并将原来的地址进行覆盖。除此之外,String底层使用private final char[] value来存储字符串,由于使用private,对外部不可见,String内部不提供直接修改的操作,所以外部没法修改,并且使用final关键字,无法修改当前value的值。

2025-06-29 22:07:21 201

原创 八股文——JAVA基础:hashCode()方法的作用与意义以及与equals方法的联动

但是现在hashcode并不知道,当遇到id相同但内容不同的两个student,hashcode会产生两个不同的散列码,这样就违背了相同的对象的散列码相同的准则。现在有一个类student,student有一个成员变量id,此时equals重写为:id相同时student相同。散列码本身并不能唯一标识对象,不同对象可能会有相同的散列码(即发生哈希冲突)。等基于散列表的数据结构中,当两个对象的 hashCode 相同,会进一步用。在容量不足时,散列表还会触发 rehash,重新分配桶位置以提升性能。

2025-06-29 21:15:11 140

原创 深拷贝、浅拷贝、引用拷贝

首先说浅拷贝,比如现在拷贝一个类的实例,实例中包含成员变量,浅拷贝会重新创建一个地址用于存储该实例,但是现在实例中的成员变量与原本被拷贝的内容拥有同一个成员变量的地址,也就是说两者对于该成员变量是共享的。或者说该成员变量仅仅是被拷贝了地址。引用拷贝相当于构建了个地址的副本,只是为引用地址新开辟了一个空间。而深拷贝是将所有的内容都进行了重建,与拷贝的内容完全隔离开的。

2025-06-29 20:36:56 87

原创 八股文——JAVA基础:抽象方法与接口的异同

接口与抽象类的核心区别在于:接口强调规范,只能包含抽象方法和常量,支持多实现;抽象类侧重代码复用,可包含变量和具体方法,但仅支持单继承。接口用于定义行为规范,抽象类则用于构建基础功能框架。

2025-06-29 20:30:43 76

原创 八股文——JAVA基础:静态方法和实例方法的区别是什么

所以静态方法和实例方法的区别就是静态方法在jvm连接、加载、初始化之后内存就固定的内容,又由于静态方法属于类,所以可以直接使用类名来调用方法,而实例方法只能使用实例名来调用。说白了,还是在考察static这个修饰词,需要了解的是,static这个关键字就是专门服务于类的,无法去修饰局部变量等其余内容,只能修饰类中的内容。如果static修饰类中的变量,那么意味着所有的实例共享这个变量,也就是仅拥有整个变量的同一个地址。如果static修饰方法,那么这个方法仅服务于类,不服务于实例对象。

2025-06-29 18:39:27 198

原创 八股文——JAVA基础:静态方法为什么不能调用非静态成员

静态方法是在jvm加载、连接、初始化之后就就会在方法区存在的,并且静态方法没有this引用,this引用就是指向类的实例,但是静态方法没有this引用,自然也就没有办法调用非静态成员。从因果关系也能说明,非静态成员必须通过实例调用,而静态方法没有办法调用实例,自然就没办法访问非静态成员。静态方法是属于类的,非静态成员是属于实例的。

2025-06-28 23:00:47 84

原创 八股文——JAVA基础:字符型常量和字符串常量的区别

String类型是线程安全的,char不是,String无论作为局部变量还是成员变量存储的都是地址,char作为成员变量时存储的是值。字符常量可以作为ASCII码来进行字符计算。字符串用“”,字符常量用“”。字符串常量无法进行字符计算。

2025-06-28 22:39:00 111

原创 八股文——JAVA基础:静态变量有什么作用

在类中对成员变量进行修饰时,此时成员变量就属于类了,因为使用static修饰之后,无论创建多少个实例,他们都共同拥有同一个成员变量,这个成员变量被其中一个实例修改,那么其余实例对应的该成员变量也会被修改。静态变量的访问方式是通过类名来进行访问的,比如Dog.isAnimal()。这个静态方法isAnimal可以直接通过类名访问。静态变量使用static关键词进行修饰,static无法对局部变量进行修饰。也就是说,所有的实例都拥有该实例的唯一地址,可以节省空间。

2025-06-28 22:31:27 91

原创 八股文——JAVA基础:成员变量与局部变量的区别

5.初始值:成员变量存在默认值,这是因为成员变量可以在创建类时手动赋值,也可以在创建类时在进行赋值,而局部变量没有默认值,需要在创建时进行手动赋值。1.从语法结构来说,成员变量可以被final和static来进行修饰,而局部变量不能被static修饰但是能够被final进行修饰。4.生命周期来说,成员变量从随着类的创建和销毁为一个生命周期;3.存储方式来说,成员变量由于存在与类中,所以存放在堆中;而局部变量是存放在堆中的。2.从意义上来说,成员变量是用于修饰类的,局部变量是用于修饰方法的。

2025-06-28 22:26:36 74

原创 八股文——JAVA基础:超过long的整数应该怎么表示

byte8位 short16位 int 32位 long64位。数组来存储任意大小的整形数据。相对于常规整数类型的运算来说,运算的效率会相对较低。

2025-06-28 22:11:07 109

原创 JUC:10.线程、monitor管程、锁对象之间在synchronized加锁的流程(未完)

2.此时线程访问临界区代码,发现Obj锁,所以去查看obj的header中的mark word中指向管程monitor的指针,从而找到monitor。由于该方法有临界区(加锁),此时在线程的栈帧中还会维护锁对象(synchronized是一个对象锁,锁住的对象需要创建对应的索引信息)的地址以及lock record(锁记录)用于存储当前线程的地址。当有其他线程发现锁对象的锁状态不为00,此时就会进行后续处理,比如自旋,自旋失败后,将后续的锁升级为重量级锁。lockrecord中记录着 当前锁记录的地址。

2025-06-28 20:48:12 358

原创 JUC:9.synchronized对象锁与线程八锁分析与线程安全问题分析

简单来讲,final固定的是对应变量的地址,这个变量的地址写在对应的类中,所以拿final修饰的变量过程实质上是从堆去拿实例化的对象的地址,然后从实例化对象的实体中拿到final修饰变量的地址,这个地址被写死了,无法修改,但是可以通过修改final修饰的对象中的变量来对final修饰的对象进行修改。两个线程拿到同一个对象,所以拿到同一个list,现在考虑一种情况,线程1添加后,线程2也添加完,现在线程1删除0位置的内容,那么线程2删除就会出现报错。如题,synchronized是一种互斥锁,用于解决竟态。

2025-06-28 15:35:48 202

原创 JUC:8.竟态与临界区

首先说临界区,juc中定义的临界区就和操作系统中的临界区是一个东西,指的就是互斥的资源,需要注意的是,即使这个资源只是读互斥,也是临界区。多个线程在临界区内执行,由于代码的。而导致结果无法预测,称之为发生了。

2025-06-27 21:33:58 102

原创 JUC:7线程的五种状态与六种状态

状态,不会进入 BLOCKED。yield()方法用于让出本轮时间轮片,而因为没有释放资源,所以本身还处于就绪状态,所以对应jvm的状态为。显然waiting、blocked、time_waiting都属于阻塞。只是提示调度器“我这次让个步子”,线程仍然处于。创建、就绪、运行、阻塞、销毁。

2025-06-27 21:29:24 224

原创 JUC:6.守护线程与主线程

对于主线程而言,假设主线程中调用多个子线程,就算主线程执行完成后,也会继续等待子线程都执行完成后才会执行结束。守护线程姿态很低,当守护线程守护的线程结束之后,守护线程不管是否完成所有内容都会立刻终止。比如垃圾回收线程GC线程就是一种守护线程。

2025-06-27 21:21:39 102

原创 JUC:5.start()与run()

这两个方法都可以使线程进行运行,但是start只能用于第一次运行线程,后续要继续运行该线程需要使用run()方法。如果多次运行start()方法,会出现报错。,它确实不会启动新的线程,而只是像普通方法一样在当前线程里执行它的代码块;的——只是不会并发,而是同步地在调用者那条线程里跑。初次调用线程使用run()方法,无法使线程运行。

2025-06-27 21:17:15 133

原创 JUC:4.线程常见操作与两阶段终止模式

在线程中,wait()、join()、sleep()三个方法都是进行阻塞的方法。对应可以使用interrupt()方法进行打断,被打断后线程会抛出打断异常,但是不会修改IsInterrupt,也就是此时去调用IsInterrupted()方法后获得的实际上是false。而当线程处于非阻塞状态时,使用interrupted()方法对线程进行打断,此时不会出现打断异常,但是会将IsInterrupt设置为true。

2025-06-27 21:14:10 141

原创 JUC:3.上下文切换

当线程1的cpu时间轮片用尽后,cpu会转向执行其他线程,为了后续接着运行线程1的后续任务,需要将线程1当前的环境进行保存。具体保存的内容,包含线程对应的栈的内容以及以及程序计数器的值。上下文切换指的是线程出现调度时,运行环境的切换。

2025-06-27 20:54:36 339

原创 JUC:2栈和栈帧的定义

这部分内容虽然是JVM中的定义,但是在juc中属于底层知识,必须要学习每个线程在创建时,就会将自身的资源存储在栈中,将线程需要运行的方法存放在方法区。栈中会存储方法的局部变量、方法的参数以及方法返回的地址,这部分在线程创建的初始化时就会被创建。栈帧对应线程执行的方法,每执行一个方法就会创建一个栈帧,这个栈帧维护当前方法的对应局部变量、方法参数以及返回地址。程序计数器用于记录当前执行到的程序,用于上下文切换。

2025-06-27 20:52:37 330

原创 JUC:1.三种创建线程的方式

创建runnable类。创建Runnable类,传递给线程。3.使用lambda表达式创建线程。

2025-06-27 20:41:46 110

原创 八股文——JAVA基础:包装类型的缓存机制了解么?

对于包装类中的整形包装类,Byte、Short、Integer、Long等,对于数值在-128到127的内容会在堆中创建缓存,比如拿Integer举例,Integer a = 10,Integer b =10,10对应在缓存数组CACHE[138],所以a == b是比较的就是CACHE[138]对应的地址,显然两者地址是相同的。

2025-06-25 23:01:12 126

原创 八股文——JAVA基础:基本数据类型与包装类的区别

1.用途不同,在目前编程而言,基本除了使用局部变量会使用基本数据类型外,都会去使用包装类。包装类能够适用泛型是目前企业编程使用包装类的主要原因,而基本类型不行。对于这个内容终于弄清了:无论是基本数据类型还是包装类还是其他引用类型,首先都是从jvm中的栈去取值,而基本数据类型拿到的是数值,而引用类型和封装类(封装类就是引用类型)拿到的是地址,地址对应在堆中。3.存储方式不同,基本数据类型作为局部变量会被存放在栈中,如果作为引用类型会被存放在堆中。2.内存占用不同,包装类的占用会大一些。对于包装数据类型来说,

2025-06-25 22:51:35 342

原创 八股文——JAVA基础:标识符与关键字

关键字是特殊的标识符,有其公认的意义,比如private、public等都是用于对方法、参数进行修饰的。标识符就是一个名字,比如我们对方法、参数取得名字就是标识符。需要注意的是true/false/null不是关键字。

2025-06-25 22:28:55 237

空空如也

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

TA关注的人

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