- 博客(32)
- 收藏
- 关注
原创 wait-notify 与 保护性暂停设计
Monitor 监视器,其实就是synchronized锁的那个对象,在Java中,每个对象都可以关联一个Monitor对象,其实例存储在堆中Thread-2 某个线程,现在是Monitor的Owner,也就是获得了当前锁EntryList 里面是未竞争到锁而阻塞等待的线程WaitSet 先前竞争到的线程,但因为没有足够资源需要wait的OWNER 线程发现条件不满足,调用wait方法,即可进入WaitSet变为Waiting状态。
2023-10-09 23:01:27
91
原创 Spring AOP
事务是开发中必不可少的东西,使用JDBC开发时,我们使用connnection对事务进行控制,使用MyBatis时,我们使用SqlSession对事务进行控制,缺点显而易见,当我们切换数据库访问技术时,事务控制的方式总会变化, Spring就将这些技术基础上,提供了统一的控制事务的接口。编程式事务控制和声明式事务控制事务控制方式解释编程式事务控制Spring提供了事务控制的类和方法,使用编码的方式对业务代码进行事务控制,事务控制代码和业务操作代码耦合到了一起,开发中不使用声明式事务控制。
2023-09-26 21:20:47
123
原创 分布式雪花算法
雪花算法(SnowFlake)是 Twitter 开源的分布式 ID 生成算法。Twitter 雪花算法生成后是一个 64bit 的 long 型的数值,组成部分引入了时间戳,基本保持了自增。高性能高可用:生成时不依赖于数据库,完全在内存中生成。高吞吐:每秒钟能生成数百万的自增 ID。ID 自增:存入数据库中,索引效率高(涉及到MySQL主键优化的页分裂问题)。依赖与系统时间的一致性,如果系统时间被回调,或者改变,可能会造成 ID 冲突或者重复。
2023-09-23 19:39:09
164
原创 责任链模式实战——优化前置业务参数校验
等同于。/*** 执行责任链逻辑* @param requestParam 责任链执行入参*//*** @return 责任链组件标识*/mark方法是做什么的?接口增加mark方法,以便不同业务使用不同的标识。假设项目中有两个业务场景:订单下单OrderCreate和用户UserCreate创建都需要责任链模式去验证,mark就是用来进行分组,在业务中进行调用责任链时传递不同的mark方法参数,通过该参数找到对应的一组责任链具体实现类集合。
2023-09-16 23:35:44
672
2
原创 MySql 锁
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。为什么全库逻辑备份,就需要加全局锁呢?对数据库进行进行逻辑备份之前,先对整个数据库加上全局锁,一旦加了全局锁之后,其他的DDL、DML全部都处于阻塞状态,但是可以执行DQL语句,也就是处于只读状态,而数据备份就是查询操作。
2023-08-21 15:09:18
37
原创 Java虚拟机内存学习
在字符串拼接过程中:如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串。如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。
2023-08-21 11:25:08
37
原创 MySql SQL优化
视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视 图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
2023-08-18 22:10:51
127
1
原创 MySql中的事务隔离级别
MySql的事务隔离级别有如下五种,如MySql中,支持事务的存储引擎的默认事务隔离级别就是RepeatableRead,可以避免事务之间的脏读和不可重复读。MySql的事务是默认提交的,也就是说,默认情况下,当执行完一条DML语句时,MySQL会立即隐式的提交事务,所以银行转账问题中的两个更新操作是割裂的。MySql的事务的一个经典解释是银行转账问题,即对转账方和收账方的两个数据更新操作应该是一个完整的不可分割的事务,否则就可能会出现并发事务问题。这些都是在并发事务的环境下发生的,
2023-08-15 23:13:50
253
原创 JDK17中HashMap的put的源码了解
源码中HashMap的构造方法都只是初始化了一下加载因子(loadFactor),没有对底层的数据结构(数组)进行初始化(起码table都没有分配内存) ,从后面put->putVal->resize方法可以得知:在第一次put元素时,才对HashMap对象的数组进行初始化!MIN_TREEIFY_CAPACITY // 允许HashMap的某些链表转为红黑树的最小数组长度阈值。//左子节点的地址值。//右子节点的地址值。Node[] table // 哈希表结构中数组的名字。
2023-08-12 22:05:55
143
1
原创 Java迭代器中,应用乐观锁应对线程不安全问题(为什么普通迭代器遍历过程中不允许使用集合对象更新集合?)
checkForComodification方法,在每次调用next方法遍历时判断:modCount与expectedModCount是否相等,如果不相等,就说明modCount在迭代器初始化后改变了(集合更新了),发生了线程不安全的问题,即抛出异常。内部类的next方法,先不看checkForComodification方法,代码块其他内容就是在做返回索引对应元素值的工作。应用迭代器遍历如下,while代码块内部允许使用迭代器删除(普通迭代器不能add)集合元素,但是不能调用集合的删除方法。
2023-08-11 22:11:43
66
1
原创 WebSocket的简单使用
WebSocket 是基于 TCP 的一种新的。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建的连接, 并进行数据传输。HTTP是WebSocket是HTTP通信是的,基于请求响应模式WebSocket支持通信HTTP和WebSocket底层都是TCP连接既然WebSocket支持双向通信,功能看似比HTTP强大,那么我们是不是可以基于WebSocket开发所有的业务功能?
2023-08-08 22:50:47
225
原创 Spring task 定时任务的简单使用
分为6或7个域,由空格分隔开,每个域代表一个含义每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)
2023-08-08 21:57:00
92
原创 Spring AOP 简单入门以及公共字段的注入
自定义注解/*** 自定义注解,用于标识某个方法需要进行功能字段自动填充处理*/@Target(ElementType.METHOD) // 指定当前注解的位置,ElementType.METHOD表示该注解只能加在方法上@Retention(RetentionPolicy.RUNTIME) // 固定写法//数据库操作类型:UPDATE INSERT/*** 数据库操作类型*//*** 更新操作*/UPDATE,/*** 插入操作*/INSERT/**
2023-08-07 18:48:31
163
原创 Redis结合异步提高并发能力
如下图所示的业务场景,用户向服务器提交购买优惠券的请求,服务器现在按顺序串行同步执行业务流程,这样业务虽然可以严谨执行,但是由于整个串行执行的时间耗费很长,特别是“减库存”和“创建订单”还是向MySQL中写的操作,这样一个线程就不得不按流程走完这个用户提交的请求才能去响应其它用户的请求。这里我们就可以想到多线程结合速度更快的Redis的思路,那把哪些业务交给Redis的线程呢?我们可以给每个业务都独立开新线程吗?显然也是不行的,如果开这么多线程一旦用户请求多起来,线程池中的线程很快就用完了。
2023-08-03 16:40:45
162
原创 分布式锁解决服务集群中的悲观锁失效问题
前面我们已经在单体服务的环境下使用悲观锁解决了“一人一单”问题,但是在分布式的集群环境下,悲观锁就不行了,如下图所示,悲观锁只在当前的JVM中有效,集群环境有相当多的JVM,每个JVM又监视不同的锁,这样悲观锁就没办法针对用户了。
2023-08-01 23:38:24
113
原创 高并发情况下的“超卖”(脏数据/并发安全)问题
以上列代码为例,正常情况下,理应时数据库中库存(stock字段)到达0就不会再减少了,但是在高并发的情况下,stock有可能出现负数的情况,这在业务中是极大的问题。(脏数据,“超卖”问题)。为什么高并发下会出现“超卖”?观察下面的时序图,正常情况下,线程执行是按顺序的,而高并发的情况下的线程不可能都是按顺序的。悲观锁认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行。例如Synchronized、Lock都属于悲观锁。悲观锁最明显的缺点就是。
2023-08-01 23:23:11
196
1
原创 缓存穿透、缓存雪崩和缓存击穿的简单了解
缓存穿透是指客户端请求的数据在缓存中和数据库都不存在,这样缓存永远不存在,这些请求都会打到数据库。攻击者可以开多个线程连续不断避开缓存去请求数据库,其实就是一直请求数据库中不存在的数据,这样Redis不会缓存,数据库就会被高量的请求一直攻击,最终就有可能数据库服务器崩掉。
2023-08-01 16:44:28
77
原创 分布式锁优化控制定时任务
我们已经实现了定时任务,如果用户体量上来了,就可能由多台服务器分摊压力,一个用户可能在某个时段访问A服务器,另一个时段又访问B服务器,而在实际业务中,可能同时有上百上千个服务器存在,每个服务器上都设置了定时任务,那会发生什么呢?浪费资源,想象 10000 台服务器同时 “打鸣”脏数据,比如重复插入怎么做?分离定时任务程序和主程序,只在 1 个服务器运行定时任务。成本太大写死配置,每个服务器都执行定时任务,但是只有 ip 符合配置的服务器才真实执行业务逻辑,其他的直接返回。成本最低;
2023-07-25 21:23:22
453
原创 缓存预热的简单实现
2)给要定时执行的方法添加 @Scheduling 注解,指定 cron 表达式或者执行频率。问题:第一个用户访问还是很慢(加入第一个老板),也能一定程度上保护数据库。XXL-Job 之类的分布式任务调度平台(界面 + sdk)预热的时机和时间如果错了,有可能你缓存的数据不对或者太老。Quartz(独立于 Spring 存在的定时任务框架)缓存的空间不能太大,要预留给其他缓存空间。增加开发成本(你要额外的开发、设计)缓存预热的意义(新增少、总用户多)缓存数据的周期(此处每天一次)不同用户看到的数据不同。
2023-07-25 21:12:17
116
原创 缓存的简单实现
分布式操作 Redis 的 Java 客户端,让你像在使用本地的集合一样操作 Redis(分布式 Redis 数据网格)如果你用的不是 SPring,并且追求简单,并且没有过高的性能要求,可以用 Jedis + Jedis Pool。如果你用的是 Spring,并且没有过多的定制化要求,可以用 Spring Data Redis,最方便。如果你的项目是分布式的,需要用到一些分布式的特性(比如分布式锁、分布式集合),推荐用 redisson。的操作 Redis 的 Java 客户端。
2023-07-25 21:04:14
36
原创 Session共享
由于HTTP协议是无状态的,在开发中我们可以将用户的信息存储在服务器的Session中,并生成与之对应的JSession,生成的JSession通过cookie返回给浏览器。该浏览器下次访问,cookie会自动携带上次请求存储的数据(JSession)到服务器中,服务器根据JSession找到对应的session,从而获取用户的信息。该机制在单体应用中是没有问题的,但是如果在分布式环境下,会产生session共享问题,即。这样会导致用户已经在服务1上登录过了,但请求服务2时找不到用户信息。
2023-07-24 13:15:23
96
原创 6、基于注解方式的Spring应用
如果非自定义的Bean需要参数,该怎么注入参数还是怎么注入参数,简单类型用@Value,引用类型用@Autowired,要根据名字注入引用类型就多用个@Qualifier,如下:这里的stl表达式${jdbc.driver}是已经被加载进入Spring容器的jdbc配置类中的键。
2023-06-16 14:05:57
49
原创 5、Spring Bean的生命周期以及整合第三方框架
如下图,getBean("userService")后,先实例化Service,开辟内存给一个地址用于存储半成品的Service,然后继续执行bean的生命周期,对Service初始化,填充引用对象userDao,但是没有userDao,就先暂停userService的生命周期,改去执行userDao的生命周期,但是userDao初始化也要填充引用对象userService,这样看起来就变成了一个死循环的问题。这样就结束了所谓的死循环,即将半成品的未初始化的bean先存在某处(反正不是单例池)。
2023-06-15 12:36:01
30
原创 4、Spring的后处理器
Spring的后处理器是Spring对外开放的重要拓展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。Spring主要有两种后处理器:1、BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;
2023-06-14 20:27:36
63
原创 3、Spring的get方法、配置非自定义的bean、Bean实例化的基本流程
配置第三方功能类中的bean,要考虑两个问题:1、被配置的Bean的实例化方式是什么?无参构造,有参构造,静态工厂方式还是实例工厂方式2、被配置的Bean是否需要注入必要属性例1:配置Druid数据源交由Spring管理 阅读Druid源码发现,Druid提供了无参构造器,我们可以使用无参构造的方式配置Bean,注入四个必须的简单类型信息,注意property的name属性必须与Druid的源码中的setter方法名对应。 例2:配置Connection交由Spring管理 Class和DriverMan
2023-06-13 16:37:26
37
原创 2、SpringBean的配置详解
在xml中配置bean时,一般我们会给出bean的id,也就是bean在xml文件中的唯一标识,而实际上实例化bean即调用getBean时,参数是beanName而非beanId,这是Spring自动将beanId作为beanName为bean工厂进行bean的实例化。prototype,原型的,Spring容器初始化时不创建Bean实例,而是到调用getBean时才实例化Bean,每次实例化都会创建一个新的Bean实例。
2023-06-13 13:33:50
144
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人