- 博客(83)
- 收藏
- 关注
原创 ForkJoin多线程分治
我们拿计算从0累加到20的算术思想举例,正常计算是从0一直加加到20,那么这样一个线程加的话当我们加的数量大或者说任务比较耗时的时候,那么就会很慢,我们就可以考虑使用多线程分治的思想,把一个任务变成多个子任务,然后最终合并结果,我们也可以手撸 使用线程池进行多个任务的进行而二者的优缺点使用场景也是不同的,就比如下面。:任务可递归拆分(如数学计算、树遍历、归并排序)。但是今天我们使用ForkJoin 分治任务框架来进行。:任务是独立的、IO 密集型或无需拆分。
2025-07-16 15:55:44
227
原创 DFS深度优先搜索(业务版)
假如我们一个节点有多个子节点,那么,就会有多个边实体,里面前面的节点id都是一样的,然后我们遍历这个图中所有的边实体,根据边的前面节点 id为key,后面节点的id集合为value,拿着这个map, 在我们设计的dfs搜索中进行查找,如果查不到,那么就不连通。这个时候我们就可以运用dfs的思路,其实这个也很像图的连通,这个头节点下面连接的有很多子节点,子节点下面也有很多的子节点,但是最终所有的节点都会汇聚到尾节点那里,如果有一个节点到不了尾节点那里,那么就是出错了。我们的节点设计是这样的。
2025-06-28 16:42:14
514
原创 自定义连接线程池
可以看到 我们用一个connection 连接数组来保证每一个连接对象,然后用一个status 的cas数组来控制每一个连接对应只能获取一次,然后添加等待唤醒放置资源的浪费。今天来实现一个小小的自定义连接线程池,主要是为了让我们对线程池有一个大致的了解。下面是我们的自定义线程池的实现。实现这个连接对象就可以了。
2025-06-08 15:24:55
224
原创 记录一次功能优化需求下的业务处理思路整理
其实在写写完上面的代码后,我发现每次要获取不同的角色,比较麻烦,那么我们可以把获取角色的这个功能,抽象到拦截器里面,然后在拦截器里面获取角色,然后存入一个统一保存用户信息的地方,比如threadlocal,或者会有人说把他抽成一个aop+注解的形式,但是如果抽成aop+注解的形式,每个接口都存储一下信息,是不是太怪了呢?比如说:查看该角色下的学生信息接口,查看该角色下教的班级的接口,查看该角色下教的不同班级的所在不同院系的接口,等这些一个一个的根据角色查询信息的接口写起来是不是太麻烦了。
2025-05-24 16:48:29
334
原创 使用FastExcel时的单个和批量插入的问题
在我们用excel表进行插入导出的时候,通常使用easyexcel或者FastExcel,而fastexcel是easy的升级版本,今天我们就对使用FastExcel时往数据库插入数据的业务场景做出一个详细的剖析。
2025-03-29 16:46:49
959
1
原创 springBoot集成emqx 实现mqtt消息的发送订阅
我们可以想象这么一个场景,我们java应用想要采集到电表a的每小时的用电信息,我们怎么拿到电表的数据?一般我们会想 直接 java 后台发送请求给电表,然后让电表返回数据就可以了,事实上,我们java应用发送请求请求电表的数据信息并不是发到电表上,而是发送到 服务端 (broker)上,请求服务器 给我们电表的信息,而电表会把数据 按照mqtt协议 源源不断的发送到服务端,服务端可以把数据存储到物联网数据库上,也可以由我们java应用手动存储到物联网数据库上。
2025-03-04 21:52:44
1198
原创 支付宝沙箱环境实现h5网站扫码支付和异步验签
用户选好商品访问网站接口--带着商品数据请求服务接口--本地服务内部调用支付宝支付接口---调用成功返回支付页面让用户支付---在用户确认支付后,支付宝通过 get 请求 returnUrl(商户入参传入),返回同步返回参数-返回一个支付成功的页面---后续是否支付成功由异步验签和主动查询来做。,我们需要设置自己的应用网关地址,这个是支付宝异步验签的请求地址,我用的内网穿透,用的本机接口,具体怎么做内网穿透,自行百度。然后弄好之后我们会得到一个 应用公钥和私钥匙 ,然后支付宝那边会有 对应的支付宝公钥。
2025-02-11 17:10:22
985
原创 定时任务框架 Quartz
定义一个类实现job 接口里面是我要执行的逻辑,用jobdetail 把这个类加入进去,然后再定义一个trigger,控制 该类要执行的时间,然后用scheduler 把二者绑定起来,就可以执行了。JobDataMap 则是 在我job类 和 调度任务类中都能拿到信息,也就是 所谓 公共一点的数据。其中 也可以跟数据库联系起来根据具体的功能,进行定时任务的添加,修改删除,立即执行等。
2025-01-09 17:03:46
265
原创 函数式编程--Function接口
什么是function接口呢?他是一个函数接口,里面有一些方法可以使用function接口应用就是我们在定义一个方法的时候,如果发现这个方法中的一些逻辑能够被抽取出来由使用者自己去定义,而且这部分逻辑需要一个返回值,那么我们就可以用function接口来进行书写我们先来看function接口的接口内容,接口中明确指定了 我们传入的参数类型为T,返回的一个参数类型是R,有一个静态方法identity,两个默认方法,一个方法我们先来看apply方法。
2025-01-05 16:02:32
460
原创 多线程设计模式-保护性暂停之面向对象
保护性暂停模式,也是多线程的一种固定模式,使用着这种模式时候,当线程在访问某个对象时,发现条件不满足时,就暂时挂起等待条件满足时再次访问。并且能够防止虚假唤醒那我们不禁要思考,在多线程终止模式的时候,用interrupt或者一个共享变量作为标记位,来进行优雅的终止,在 保护性暂停的时候呢,也是 传入一个由线程定义的时间变量,发现条件不满足,进入 等待,即使其中被虚假唤醒,只要条件不满足,我们仍进入挂起状态,直到设置的等待时间结束。
2024-12-19 10:53:25
606
原创 多线程-虚假唤醒与notify与wait
孩子们,假如现在有 a b 两个线程,都调用wait方法,在montior 中的waitset中陷入等待,但是 此时 你调用了 natify方法,想让a线程运行,让b线程 等待,由于 cpu时间片是随机分配的,你无法控制 谁先抢到cpu的时间片,这时候就容易导致b线程 被唤醒了 ,你想要的a 线程没有被唤醒 这时候 就出现了虚假唤醒的情况。
2024-12-14 16:47:55
277
原创 多线程中interrupt的 两阶段终止模式
我们先思考一下,如果 一个线程正在运行中,我们如何 把该正在运行的线程终止运行,我们可以看到 在 线程api中 有 stop方法,或者 system的exit 方法,但是 这种 直接 终止的行为 不够优雅,而且太暴力,假如 有一个线程 再打断后 还需要 做一些 处理逻辑的话 ,那么用stop,或者 exit 方法 就不太合适了就好像 我们 工作中 离职一样,我们是 直接被开除,什么都不管当天就走,还是 自己 开除的时候 办一些手续,显然被开除不太好 ,但是相对来说还是第二个 更加合理且负责一点。
2024-12-08 15:50:15
353
原创 开闭原则与访问修饰符 中 的线程安全问题
所以由此可以说明,访问修饰符在一定程度上 是有用的,能够带来 线程的安全性,同时 我们 可以让我们的方法设置为 对外 扩展开放,对修改闭合。当我们一个类 中公共的方法本来是线程安全的, 被子类重写之后改变了逻辑,并且有新的线程去运行,这时候 就不是 线程安全的了。而我们使用 private修饰方法3,让他不能 被子类重写,这时候 就不会出现线程安全了。
2024-12-01 17:10:50
251
原创 变量的线程安全性
那么我们第一个线程不安全能否进行改进呢,答案是可以,我们在 不安全情况下的 userdao虽然是共享的, 但是我们可以把 userdao中的成员变量 变成 局部变量, 这样 虽然我们引动用的userdao对象在method1方法作用范围之外,但是 userdao中 并没有能够导致线程不安全的情况发生,所以他就是线程安全的。因为 每个线程有存在一个栈空间,方法被调用的时候局部变量会在 每个线程的栈空间中都创建一份,所以他是线程安全的。如果 引用的对象 在方法的作用访问范围内 ,他是线程安全的。
2024-12-01 16:30:26
704
原创 ArrayList的toArray原理与 System.arraycopy
1.当我们 new 一个arraylist的时候,我们不去添加元素的时候而且并未给该集合分配空间的时候,该arraylist会默认初始化一个默认的空object数组,不会去真正的分配容量,只有当我们添加元素的时候才会真正的去分配默认容量 10,这样做的目的是什么,显而易见 是为了节省内存空间,提升效率。当我们 在list集合中传入一个数组的时候,这时候我们调用toarray方法,得到的新的数组对象,他虽然也是在堆中新new的,但是 他指向的是原来数组的在栈空间的地址。Java 将内存空间分为堆和栈。
2024-11-24 11:52:42
609
1
原创 冒泡排序-选择排序
什么是 冒泡排序,就是让两个元素 两两比较,然后 把大的元素往后移动,把无序的排序成一个有序的 ,这么说 可能看不太懂 , 我们举个例子假如数组中 又 { 5 , 4,3 ,2 ,1}这五个元素我们 先让5 和4 比较 ,谁大,就让谁交换 , 显然 5大于4,需要交换 交换后数组变成了 { 4,5,3,2,1}然后进入第二轮 让 5 和 3 比较 谁大交换 ,直到比到1 的时候 ,数组变成了 {4,3,2,1,5}
2024-10-31 22:20:13
365
1
原创 CAS 工作方式-无锁并发安全
我们在cas也就是Compare-And-Swap,简写为cas,我们先不去想什么是cas啊,我们先来想我们在多线程情况下要修改一个变量的话,在不加锁的情况线程一旦开始就要一直运行到结束,这时候变量就会出现线程安全的问题,比较典型的是票的超卖问题,但是如果我们加锁的话,因为涉及到线程的上下文切换,阻塞等就不可避免的会出现效率变低的问题。而cas 就根据乐观锁的思想,对一个变量的修改,来进行 不加锁保证效率的情况下,来对该变量进行 安全的并发修改。
2024-10-30 18:45:29
424
原创 redis的bitmap实现用户签到天数统计
我们知道 redis中的bitmap对应有二的三十二次幂个bit位,我们们统计每个用户当前月的 每一天的是否签到,我们只需要把月份跟bit位进行 对应,比如现在是 2021年的10月,我们把10月1号当天是否签到对应第一个bit位,签到了把对应bit位改为1,没有签到,就使用原始数字0,这样就能完成签到功能。
2024-10-22 17:46:33
605
原创 redis的zset实现下滑滚动分页查询思路
我们redis的数据为我们知道 我们常规查询的话 我们假如 zset 表中 有7个元素,然后我们进行分页查询的话,我们一次查3个元素,然后查出来元素 和元素的分数我们redis的语法应该这样写这句话的意思是 我们根据score的分数 从大到小开始查询 查询的是 小于等于1000 大于0 的score 和他的member,从0开始查,也就是从1000开始查,差三个元素 ,这时候我们redis得到的数据应该为。
2024-10-18 17:52:47
883
原创 redis同步解决 缓存击穿+缓存穿透 原理代码实现
/互斥锁解决缓存击穿//解决缓存击穿//走到这里 代表着 缓存查不到了//1. 获取 redisson 互斥锁//2. 获取不成功 自旋等待try {log.info("获得到了锁");//2. 获取成功查询数据库 返回缓存数据//没有的话查数据库//数据库有的话 添加缓存并且返回// 设置过期时间 防止内存 占满//数据库没有 返回false//解决缓存穿透 访问不存在的数据 缓存为null值 并且设置过期时间log.info("缓存穿透 构建了新数据");
2024-10-10 20:38:57
512
原创 redis+mysql数据一致性+缓存穿透解决方案
在分布式事务中我们知道有cap定理,即 我们保证高可用的情况下,必然要牺牲一些一致性,在保证强一致性的情况下,必然会牺牲一些可用性。而我们redis+mysql数据一致性的使用策略就是在我们保证可用性的情况下尽量保证数据的一致性。想要达到强一致性,不加锁,只用 一些缓存策略那必然不是不可能的。
2024-10-06 22:56:09
1608
5
原创 设计模式-装饰者模式
装饰者模式,顾名思义 就是对一个类进行装饰,装饰类叫做装饰者首先 我们根据咖啡为例子1. 我们进去一个咖啡店 (咖啡接口)2.咖啡店 的这款基础咖啡的描述 (实现咖啡接口的 基础咖啡类)3.有一个基础款式的咖啡,我们后面点的所有咖啡都会在这款基础咖啡上进行修改(同时也是我们 的被装饰的类,)4. 我们现在 不想要基础款的咖啡,现在我们想要牛奶咖啡,并且加糖,那么我们就要 把基础咖啡 装饰成 牛奶咖啡,然后加糖 ,我们新写一个牛奶咖啡类来当装饰者,装饰这款基础咖啡,并且加上条件。
2024-09-22 20:56:31
532
原创 二叉树的层序遍历-广度优先遍历
5.然后 我们再把头节点左右孩子加入队列 【2,3,4,5】然后头节点出队变成【3,4,5】,然后再把头节点左右孩子加入队列【3,4,5,6,7】然后头节点出队打印,依次循环,直到队列为空。首先我们分析 一个二叉树 如上图我画的那个二叉树,第一层 一个元素,第二层 两个元素,第三层是四个元素 ,我们可以打印出 每一层的元素之后,让该元素换行,就可以得到树形结构的二叉树,我们可以引入一个临时变量,来记录我们每一层的元素个数,然后根据我们每一层添加的元素个数,来进行遍历打印。下面来看一下代码实现。
2024-09-12 10:44:08
535
原创 归并排序-非递归实现
源代码如下,我们的merge的合并函数的参数是 原数组,左侧小数组索引位置开头,左侧小数组索引位置结束,右侧小数组索引位置开头,右侧小数组索引位置结束,要拷贝的数组。最小单元 合并一次之后,我们继续 在上一次合并的基础上拆分,并且合并这是。拆分成最小单元之后,我们对每个最小单元进行一次合并,这是。直到 整个数组 只被拆成了两部分,在进行最终一次的和。我们可以把 一个数组 先拆分成 最小单元,这是。归并排序的非递归实现。
2024-09-07 11:19:12
372
原创 阻塞队列-单锁实现
使用阻塞队列当我们多个线程下 对 一个队列进行操作,队列满了的情况下,其他线程再次 offer,会一直阻塞等待对一个队列进行出队操作的时候,队列空的情况下,会一直阻塞等待删除,直到队列有元素的时候,会执行删除操作一直阻塞等待的时候用自旋锁来进行等待代码如下。
2024-09-03 22:14:51
495
原创 堆排序-优先级队列
我们用堆排来实现优先级队列,那么优先级队列是什么,就是 我们给每一个任务都添加一个优先级,优先级越高执行的越早我们用,但是我们怎么能按照顺序优先拿到优先级高的任务呢,我们可以用排序 来进行,也可以用堆 排序来进行,效率更高如上图 索引0 为 根节点 也就是parent,那么我们如何找到 他的 叶子节点呢?如果用比大小直接排序的话,就不是堆排序,堆排序本质 就是用有序数组的形式,来形成树型结构,当我们知道 parent结点之后,他的child节点就遵循如下规律上浮。
2024-08-18 12:41:36
535
1
原创 消息队列-rabbitmq(生产者.消费者. 消息.可靠性)
在我们 生产者发送消息到交换机的时候,假如 我们发送到交换机 ,但是 队列没有收到消息,会返回ack,发送到交换机,然后发送到队列,消费者没有接收到消息返回ack,但是发送到交换机失败,会返回nack。死信交换机 ,都是假如一个定时消息过期了,或者发送延迟消息我们直接把该消息传递到我们绑定的死信交换机中,跟上文 消息发送失败了返回rejct之后,消息发送到err交换机是两种不同的策略。当一条消息发送失败的时候,消费者重新尝试消费消息,达到我们重试的次数之后,消费者返回reject,mq直接删除消息。
2024-07-28 16:45:11
1275
原创 消息队列-RabbitMq
rabbitmq的下载安装使用就不再叙述,直接看我们的demo工程我们知道 我们发送一条消息 到rabbitmq 中,首先是交换机接收到消息,然后交换机把消息发送到队列当中去,由消费者消费队列的中的消息。
2024-07-27 11:38:45
543
原创 网关路由的实现及使用
最终的请求转发是由 nettyroutingfilter进行的,所以我们的自定义登录鉴权 +用户信息的配置的路在请求转发到微服务之前来完成,也就是nettyroutingfilter之前,所以我们需要给我们的过滤波器也设置一个优先级 我们直接看实现代码。好,那么现在 我们到 把请求转发到微服务了,我们的服务在接收的时候需要解析出来我们设置的请求 信息,然后把请求信息传递到整个实例中 , 我们怎么解析嘞,当然是请求进入实例的时候加一个拦截器就可以啦。
2024-07-22 23:50:18
592
原创 git 操纵分支和标签
我们再git 上传代码时候,假如 master主分支 提交到第五次了,但是突然发现 第三次提交的代码有bug,我们可以 新创建一个分支,然后回退到第三次提交之后的代码,解决bug之后,合并分支。检出标签的时候,需要新创建一个分支,来装标签的代码以及内容。我们只需要知道 每一个分支都是独立的进行的,假如 我们在。
2024-07-16 17:41:07
332
空空如也
easyx背景图片不显示
2023-08-16
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅