
JAVA
文章平均质量分 86
null_null_bug
这个作者很懒,什么都没留下…
展开
-
RabbitMQ消息可靠性保证机制--发送端确认
RabbitMQ后来引入了一种轻量级的方式,叫发送方确认(publisher confirm)机制,生产者将信息设置成confirm(确认)模式,一旦信道进入了confirm模式,所有在该信道上面发送的消息都会被指派成一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后(如果消息和队列是持久化的,那么消息会在消息持久化后发出),RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一的ID),这样生产者就知道消息已经正确送达了。原创 2023-09-24 19:52:38 · 438 阅读 · 0 评论 -
RabbitMQ工作模式-主题模式
top类型的交换器背后原理跟direct类型类似只要队列的bingingkey的值与消息的routingKey的匹配,队列就可以收到该消息。使用topic类型的交换器,队列绑定到交换器、bingingKey时使用通配符,交换器将消息路由转发到具体队列时,会根据消息routingKey模糊匹配,比较灵活。使用topic类型的交换器, routingKey就不能随便写了,它必须是点分单词,单词可以随便写,一般按消息的特征,该点分单词字符串最长255字节。观察可以发现,此队列与消息的绑定已经成功。原创 2023-08-30 21:57:54 · 555 阅读 · 0 评论 -
RabbitMQ工作模式-路由模式
官方文档参考:https://www.rabbitmq.com/tutorials/tutorial-four-python.html。即按日志不同的级别,分发到不同的队列。每个队列只处理自己的对应的级别日志。类型的Exchange,发N条消息并使用不同的routingKey,消费者定义队列并将队列。完成匹配的情况下消息才会转发到对应的队列中被消费。启动消费者,查看消息通否被正常消费。ERROR的消费者控制台输出。创建WARN级别的消息者。创建ERROR的消费者。创建INFO级的消费者。原创 2023-08-30 21:55:29 · 1167 阅读 · 0 评论 -
使用redis进行分布式加锁实现
1 redis分布式加锁现在业务并发量越来越大,像传统的数据库操作,已经不能满足要求了,这个时候可以使用redis来提升性能,同时也可以使用redis实现分布式锁。使用redis实现分布式锁,与java的synchronize类似,只不过是synchronize锁单对象,而分布式锁是锁进程或者线程,同样的它是一个独占锁,一旦被某个线程拿到锁,其他的线程或者进程,只能进行等待后再获取。当线程或者进程使用完毕释放锁后,其他线程才能获取到锁。下面将基于redis实现一个分布式锁。代码实现先看Redis的原创 2021-05-30 13:01:51 · 545 阅读 · 0 评论 -
使用数据库进行分布式加锁实现
1.使用数据库进行分布式加锁行锁以mysql为例,进行举例 :1.1 for update在mysql中使用for update获得行锁。for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级锁,则该用户可以更新也可以查询也可以更新被加锁的数据行,其他用户只能查询,不能更新被加锁的数据行,如果其他用户想更新该表中的数据行,则也必须对表施加行级锁。释放行级:1.执行提交commit语句.2.退出数据库3.程序停止运行.通常情况下,select语句是不会对数据加锁的,妨碍影响原创 2021-05-25 20:27:13 · 757 阅读 · 3 评论 -
总结JAVA中的锁
总结JAVA中各种锁的使用1. 为什么要使用锁? 拿个生活中的示例来说明这个问题吧,某超市做促销,菜仔油半价卖,35块钱一桶。这消息一出必然会有很多的人抢购。但菜仔油不是无限供应的,超市通常会把菜仔油放到一个地方,每次放进去一个或者两个人。这些人先购结束了,再放下一波人,直到油卖光了,就结束了。类比卖超市,想像下单程序是不是也是这样子呢,我们的客户通过网页或者手机下单商品。服务器在收到请求后都需要进行扣减库存操作。当非常多的客户同时下单了某一个商品。这样导致大量的请求都需要去扣库存。这时候我们原创 2021-04-23 09:11:02 · 325 阅读 · 0 评论 -
java实现异步非阻塞的几种方式-消息中间件
java实现异步非阻塞的几种方式-消息中间件4. 消息中间件在前面已经实现了异步调用、接口回调两种形式,都较为复杂,需要自己控制多线程,那有没有简单点的方式来实现异步的消息通讯。这个当然是有的,可以使用消息中间件的形式,来实现整个消息的异步调用。还是以订单这个场景为示例来举个粟子。4.1 样例代码我的样例程序使用rabbitmq来做为消息队列传输数据,其他消息队列功能类似。先从订单服务开始。@RestController@RequestMapping("/order")public cla原创 2021-03-23 22:17:03 · 693 阅读 · 0 评论 -
java实现异步非阻塞的几种方式-接口回调
java实现异步非阻塞的几种方式-33. 接口回调在异步阻塞的调用过程中线程还是会存在于阻塞中。等待响应的结果,那能不能在发起请求后就不再关心这个逻辑,而执行其他的任务呢?那就要用到callback机制。还是以订单查询为示例。先来说下整个的调用链吧。当这个异步回调机制加入之后,原来order的等待的结果的响应就不存在,可以做其他的事情去了,等着其他用户和商品服务完成之后,调用即可。3.1 样例代码订单服务的代码:@RestController@RequestMapping("/order"原创 2021-03-14 22:45:28 · 1073 阅读 · 0 评论 -
java实现异步非阻塞的几种方式-异步调用
java实现异步非阻塞的几种方式-2异步调用,就相关于将原来同步调用的代码块放置到一个又一个的线程中去执行,这样就可以并行的执行相关的任务。也就不用卡在一个点的等待,进而影响后续的任务。还以是订单为示例,演示整个调用的过程。2. 异步调用2.1 样例代码首先加入的就是线程池public class ScheduleTaskThreadPool { /** 进行任务调度的线程池对象 */ public static final ScheduleTaskThreadPool INSTANCE原创 2021-03-14 22:42:55 · 1886 阅读 · 0 评论 -
java实现异步非阻塞的几种方式-同步阻塞调用
java实现异步非阻塞的几种方式-11. 同步阻塞调用在讲异步非阻塞之前还是先来说明同步阻塞的调用吧。明白了同步阻塞的调用,才能更好的明白异步非阻塞的调用。以一个示例来说明吧,这是一个非常常见的程序间的调用。我们的程序对外提供当前的用户的订单详细查询的接口,订单接口先调用用户服务,获取当前的用户信息;再调用商品接口获取商品的详细信息。就以这样一个示例程序来说明吧。假设这个订单服务调用用户服务的时间是2秒,调用商品服务的时间是3秒,订单服务自身的处理时间是1秒,那整个处理流程所需的时间就是2+3+原创 2021-03-14 22:38:49 · 651 阅读 · 0 评论 -
性能测试工具-WRK
性能测试工具-WRK使用1.简介wrk是一款针对http协议的基准测试工具,它能够在单机多核CPU的条件下,使用系统自带的高性能 I/O机制,如epoll,kqueue等,通过多线程和事件模式,对目标机器产生大量的负载。2.优劣势2.1优势:轻量级性能测试工具;安装简单(相对 Apache ab 来说);学习曲线基本为零,几分钟就能学会咋用了;基于系统自带的高性能 I/O 机制,如 epoll, kqueue, 利用异步的事件驱动框架,通过很少的线程就可以压出很大的并发量;2.2劣势:原创 2021-03-07 14:03:22 · 1973 阅读 · 0 评论 -
java调用shell脚本和命令-ProcessBuilder方式
java调用shell脚本和命令-ProcessBuilder方式在上一节中,我使用Runtime的方式,实现了对命令行和脚本文件的运行。最后我留下了一个小小的问题那就是这个InputStream和errorStream需要分开获取,那有没有其他方,不用分开获取流呢?1.相关文档答案当然是有的,这就是这章节要使用的ProcessBuilder方式了。同样的,也先看下ProcessBuilder的API吧。类用于创建操作系统进程。每个 ProcessBuilder 实例管理一个进程属性集。sta原创 2021-02-28 22:53:39 · 6651 阅读 · 6 评论 -
leetcode 599. 两个列表的最小索引总和 求解思路
leetcode 599. 两个列表的最小索引总和 求解思路先来看下题目:599. 两个列表的最小索引总和假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。示例 1:输入:["Shogun", "Tapioca Express", "Burger King", "KFC"]["Piatti", "原创 2021-02-28 11:51:39 · 277 阅读 · 0 评论 -
Java调用Shell命令和脚本-Runtime方式
java运行shell脚本和命令-Runtime方式使用java调用命令行在项目的开发中经常会使用到,在我最近的一个项目中,也使用到了java调用命令和shell脚本。我将用这篇文章记录下来java调用命令行的实现。这个是java中使用最多的一种方案吧,对于Runtime在JAVA的API中是这样解释的:每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。原创 2021-02-27 16:42:26 · 1751 阅读 · 6 评论 -
leetcode 599. 两个列表的最小索引总和 求解思路
先来看下题目:599. 两个列表的最小索引总和假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。示例 1:输入:["Shogun", "Tapioca Express", "Burger King", "KFC"]["Piatti", "The Grill at Torrey Pines", "Hu原创 2021-02-26 09:09:19 · 333 阅读 · 0 评论 -
一致性哈希算法
一致性哈希算法一. 传统的哈希算法的局限性要了解一致性哈希算法,就得先了解传统的哈希算法在分布式场景下的局限性。哈希算法就是按键值对的存储,给定一个键,可以做到O(1)的时间复杂度内的数据查找。例如根据学生的学号查找学生的相关的信息。一种简单的存储形式就是以哈希表的形式来存储<code,studentinfo>。假如某个学校的学生太多了。一台机器上的哈希表已经存储不了。需要使用多台机器来进行存储学生信息,那这时该怎么办呢?这个最简单的办法就是使用哈希取模来确定,计算公式如下节点编号=h原创 2021-02-21 18:53:53 · 822 阅读 · 0 评论 -
java踩坑之线程池
java踩坑之线程池就有前几天刚完成的大型对比时使用到了线程池,对于线程池,我想我有好多踩过的坑的经历,这也就是所说的经验吧,我想通过这篇文章,将我所踩过的坑,都记录下来.坑1-newFixedThreadPool程序问题演示:这是jdk提供的一个默认线程线程池的实现。创建一组固定大小的线程池,来运行任务。当时这个任务是用来运行后台的异步发送通知任务。每秒大约100个发送量,高峰时段大约500个发送量,量并不大。但有一天通知服务突然宕机了,而我们服务调用超时的时间是2分钟,结果就导致我们的服务出现了原创 2021-02-17 13:21:12 · 1111 阅读 · 1 评论 -
单台机器上实现TB级的数据对比之数据合并
在单台机器上实现TB级的数据对比之数据合并整体思路在上一章节,我介绍了如何对切分后的数据进行并行排序,这节来到了最后的操作,数据的合并操作。将数据进行对比,找出添加的数据、修改的数据、删除的数据。需要特别处理下重复的数据。在第一章节我已经介绍了这个大致的思路,但未深入细节来讨论如何实现,这章将深入细节将数据合并的逻辑做一个完整的说明。这个逻辑看着有点复杂吧,那我来详细的解释下吧!在原始排序文件中读取所有文件的首行数据,并记录到以文件索引为下标的数组中。就叫它srcDataList在目标排原创 2021-02-17 09:50:30 · 406 阅读 · 0 评论 -
单台机器上实现TB级的数据对比之数据排序
在单台机器上实现TB级的数据对比之数据排序整体流程在上一个章节已经实现了对大型文件的拆分.今天来继续分享关于数据的排序。文件排序的逻辑不复杂。将数据读取进内存中然后排序。写入至磁盘中。由于这些文件相互完全不关联。可以并行化处理。那先还是看下整体的一个结构吧。这个主要涉及到以下内容:并行排序控制器,它的主要作用是控制向线程池中加入任务的数量。线程池,用来执行当前的排序任务。排序任务。将排序中涉及的到操作,封装到一个任务中。包括从文件中读取数据到内存,再将内存中的内容进行排序,最后再将排序后的原创 2021-02-17 09:46:41 · 405 阅读 · 0 评论 -
在单台机器上实现TB级的数据对比之数据切分
在单台机器上实现TB级的数据对比之数据切分文件切分的逻辑由于面对的原始文件可能是一堆小文件,也可能是一个很大文件,这第一步当然是对文件进行切割规整,统一大小为32M,这个32M是一个近似值,由于要保留完整的行,故这是一个接近值。那如何实现呢?分为两部分来说吧,第一部分是文件读取:读取目录下的文件,获得一个文件列表。列表使用数组来存储。将列表按文件名进行排序,获得数据读取文件的一个顺序,也就是数据的一个顺序。声明一个索引编号,编号从0开始,这个索引编号代表的就是当前正在读取的文件。按索引编号原创 2021-02-17 09:42:46 · 244 阅读 · 0 评论 -
在单台机器上实现TB级的数据对比
在单台机器上实现TB级的数据对比前几天我在做公司项目的时候,需要对数据进行比较。数据量不大,也就几千条而已。当时功能完成后,我开始思考一个问题。就是当对比的文件是特别大的时候,我还能实现吗?那现在对问题做出假设:问题:现在有两个超大文件集,原始数据集和目标数据集,每个文件集中都有超过1亿的记录,数据中存在重复的记录,编写一个程序,可以找出两个数据集之间的差异,求解出三类数据:原始数据集中存在,目标数据集中不存在,为待删除的数据记录。原始数据集中存在,目标数据集中也存在,但内容不一致,为待修改的记录原创 2021-02-07 15:52:39 · 314 阅读 · 0 评论 -
跳表加散列表实现有序的散列表(MySkipListHashMap)
跳表加散列表实现有序的散列表(MySkipListHashMap)介绍有序的,还是散列表,是不是听起来就觉得这不太现实啊!但现实往往就是这么打脸,听起来不可思议的东西,却是可以做到的。散列表,一个无序的数据结构。通过散列函数将数据散列分布到各个数据的槽里。那如何保证数据的有序呢?在java的库中有一个是实现的有序的数据结构LinkedHashMap,按照插入顺序来保存的有序,这个数据结构是通过散列表与双向链表的结合,来实现的一个保存数据。受此启发。我来实现一个按照数据的顺序来保存的有序数结构。操作:原创 2021-01-31 14:28:02 · 319 阅读 · 0 评论 -
手写LinkedHashMap
手写LinkedHashMap在上一篇博客,我实现一个MyHashMap,那今天继续来实现一个LinkedHashMap,LinkedHashMap相对于HashMap保存了数据插入的顺序,觉得神奇的,HashMap我们都知道,通过散列函数,将数据分散到不同的槽中,再从槽中去读取数据。这一过程听起来就是无法保证顺序的。那要如何保证插入的顺序呢?其实在LinkedHashMap中,加了下一个双向链表。 /** * HashMap.Node subclass for normal Link原创 2021-01-23 15:43:59 · 231 阅读 · 0 评论 -
跳表加散列表实现HashMap
自己实现HashMap在平时的开发中,jdk库中的HashMap是我们在平时的开发中用的非常多的容器之一,我常常在想,自己能否也实现一个呢?以前觉得非常的复杂,但当我学习了跳表,和散列表后,我觉得这个问题我可以尝试了,于是就开始了自己实现MyHashMap之旅。1. 需求定义既然要实现一个HashMap,那还是先需求吧。public class MyHashMap<K, V> { public MyHashMap(int capacity){} public void put(原创 2021-01-16 11:39:13 · 346 阅读 · 0 评论 -
快速排序
快速排序的基本思想快速排序也是利用分治的思想。如果需要排序的数据的下标是从s到t,在下标s到t之间的任意一个数据作为分区点p,遍历s到t之间的数据,将小于分区点的数据放到分区点p的左边,将大于分区点的数据放到分区点的右边,分区点放在中间,经过这一操作后。数据被分为3个部分,s到p-1之间为小于分区点的数据,p+1到t之间为大于分区点的数据,p为分区点。根据分治递归的处理思想,可以递归排序s到p-1的区间和p+1到t的区间,直到区间缩小为1,说明排序完成,所有数据都已经为有序。文字还是没有图直观:分区点原创 2021-01-08 18:08:26 · 294 阅读 · 0 评论 -
跳表
跳表针对链表这种数据数据结构,捎加改造,可以支持类似“二分”的查找算法,这就是跳表。如何理解跳表对于单链表来说,即使存储的数据是有序的,如果在链表中查找某个数据,也只能从头到尾依次遍历,时间复杂度会很高,是O(n)。对于单链表如何提高查找效率呢?可以类似图中如下做一级“索引”,这样子查询起来就会快很多,每两个节点抽取一个结点到上一级,可以把抽取出来的叫作索引。图中down表示down指针,指向下一级。以查找6为例,首先可以遍历一级索引,当遍历到节点为5时,索引的下一个节点为7,大于需查找到6,原创 2021-01-01 22:40:25 · 229 阅读 · 0 评论 -
重构实例-消息发送-使用策略进行重构-枚举方式-7
7. 重构实例-消息发送-使用策略进行重构-枚举方式由于这是一个长文,分成了好几章来介绍如何重构。原始代码及准备职责独立去除static关键字接口添加转换方法方法合并使用策略进行重构-Map方式使用策略进行重构-枚举方式经过上一次的重构我想你基本理解了使用map的策略模式,我们再来看使用策略模式的另一种实现list7.1 重构步骤这个还是规矩检查单元测试。使用枚举将类型与实例相绑定。进行策略的实现。执行单元测试。7.2 检查单元测试这个单元测试没有变化,可跳过7.原创 2021-01-01 22:39:59 · 164 阅读 · 0 评论 -
重构实例-消息发送-使用策略进行重构-Map方式-6
6 重构实例-消息发送-使用策略进行重构-Map方式由于这是一个长文,分成了好几章来介绍如何重构。原始代码及准备职责独立去除static关键字接口添加转换方法方法合并使用策略进行重构-Map方式使用策略进行重构-枚举方式6.1 问题分析经过前两轮的重构之后,已经提取了抽象接口,并将其static去掉。还为消息发送接口添加了转换方法,并对代码进行了方法的合并操作。经过这几轮的修改,代码已经看起来整洁、清晰了许多。但是还存在一个问题,那就是每当要添加一个新的渠道的时候,就得改动Mess原创 2021-01-01 22:39:43 · 168 阅读 · 0 评论 -
重构实例-消息发送-方法合并-5
5.重构实例-消息发送-方法合并由于这是一个长文,分成了好几章来介绍如何重构。原始代码及准备职责独立去除static关键字接口添加转换方法方法合并使用策略进行重构-Map方式使用策略进行重构-枚举方式经过前两轮的重构之后,已经提取了抽象接口,并将其static去掉。还为消息发送接口添加了转换方法。经过这几轮的修改,代码已经看起来整洁、清晰了许多。那还有槽点吗?public class MessageSender { public void sendMessage(Stri原创 2021-01-01 22:39:17 · 200 阅读 · 0 评论 -
重构实例-消息发送-添加转换方法-4
4.重构实例-消息发送-添加转换方法由于这是一个长文,分成了好几章来介绍如何重构。原始代码及准备职责独立去除static关键字接口添加转换方法方法合并使用策略进行重构-Map方式使用策略进行重构-枚举方式经过前两轮的重构之后,已经提取了抽象接口,并将其static去掉。经过这两轮重构后,有没有什么设计是不合理的呢?再次回收代码中:public class MessageSender { public void sendMessage(String msgType, Messag原创 2021-01-01 22:38:38 · 196 阅读 · 0 评论 -
重构实例-消息发送-去除static关键字-3
3. 重构实例-消息发送-去除static关键字由于这是一个长文,分成了好几章来介绍如何重构。原始代码及准备职责独立去除static关键字接口添加转换方法方法合并使用策略进行重构-Map方式使用策略进行重构-枚举方式现在来思考下NotifySendUtils中直接调用发送代码的做法,是否合理呢?或者说在我们原来的代码中,增加了一层调用,有必要吗?我觉得这个问题得分场景来看,如果是一个大系统中的一部分,NotifySendUtils被几十甚至上百的文件引用,那么这样的改动是相当合理的,原创 2021-01-01 21:26:11 · 200 阅读 · 0 评论 -
重构实例-消息发送-职责独立-2
2. 重构-策略模式-职责独立由于这是一个长文,分成了好几章来介绍如何重构。原始代码及准备职责独立去除static关键字接口添加转换方法方法合并使用策略进行重构-Map方式使用策略进行重构-枚举方式现在来分析下代码的问题先从入口MessageSender开始吧,这个类第一眼看上去,觉得很简单吧,就是按类型判断下,执行NotifySendUtils类中的发送逻辑代码。这样子看这个类没有什么大的问题么,再说NotifySendUtils吧,它封装了各种发送渠道的调用方法,还做成了静态方原创 2020-12-26 11:56:18 · 248 阅读 · 0 评论 -
java如何避免传递null-空对象模式
java如何避免传递null-空对象模式示例代码:public class CustomerFactory { private static final String[] DATA = {"1", "2", "3"}; public RealDataQuery query(String query) { for (String dataId : DATA) { if (dataId.equals(query)) { return new RealDat原创 2020-12-05 17:51:10 · 1306 阅读 · 0 评论 -
学习笔记-数据传输之零拷贝
零拷贝的性能差异先来有个直观的数据展示下,零拷贝相比传统的数据拷贝能有多大的差别,这一组数据,是我在我的笔记本电脑上测试后对比。测试的源码地址:zero测试的代码:https://github.com/kkzfl22/demojava8/tree/master/src/main/java/com/liujun/network/zerocopy/...原创 2019-09-15 22:50:50 · 246 阅读 · 0 评论 -
自己动手实现搜索引擎之数据采集
自己动手实现搜索引擎之数据采集曾经在学生时代,就很想实现一个自己的搜索引擎,但当时没有这个技术,偶然的一个机会,有幸参加了王争老师的《数据结构与算法之美》的课程,在这个专栏里,我感觉通过几个月的练习,觉得自己的数据结构与算法,有了很大的进步,老师还特别分享了自己动手实现一个搜索引擎的原理以及关键的技术点,通过这个的学习,我了解了一个简单的搜索引擎的原理与实现,我也就将自己动手实现搜索引擎的技术...原创 2019-08-03 15:43:19 · 1311 阅读 · 0 评论