记阅读ArrayList源码
基本介绍 ArrayList****集合介绍 List底层基于动态数组实现 数组结构介绍 增删慢:每次删除元素都需要更改数组长度,拷贝以及移动元素位置 查询快:由于数组在内存中是一块连续空间,因此可以根据地址+索引的方式快速获取对应位置上的元素 ArrayList的类图首先进入ArrayList源码后,ctrl+alt+u打开类图 可以清除的看到,ArrayList继承了AbstracList,并且还实现了三个接口,从它的代码中也可以看出来 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 继承关系分析Serializable标记性接口介绍:类的序列化由实现java.io.Serializable接口的类启用。不实现此接口的类将不会使任何状态序列化或反序列化。可序列化类的所有子类型都是可序列化的,序列化接口没有方法或字段,仅用于标识可串行化的语 ...
AOP加自定义注解实现防重复提交
所谓重复提交,也就是是我们经常体提及的接口幂等性。这个问题在很多场景下会出现,因为我个人版的内推蛙小系统用的服务器不算太好的,所以我自己在使用的时候会有一些问题,那就是重复提交内推帖子的问题,目前我已经采取了下面我提及的三种方法的第三种AOP加自定义注解的方式解决了这一问题。 重复提交可能出现的场景 前端按钮 卡顿刷新 恶意操作 带来的问题 数据重复或者错乱 增加服务器压力 解决方案 按钮置灰 这种方式实现起来比较简单,就是在前端保证,在第一次提交后,把按钮给置灰,不让用户多次点击 建立唯一索引 如果网络不好,用户在网页端自行刷新,这样按钮置灰就没什么用了,所以我们可以在数据库层面添加一个唯一索引,这样就不会出现重复的数据了 AOP+自定义注解 这就是我在项目中采用的方案了。下面看看是怎么实现的。 自定义注解类@Target(ELementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface RepeatSubmit{enum Type {PARAM,TO ...
项目中设计模式的使用
设计模式的优雅不必多说,最近也是好好研究了一下,利用设计模式给我的项目做了好多优化,优化过后代码果然变得很漂亮。接下来盘点一下我都做了哪些优化。 责任链模式+迭代器模式优化实现内推帖子审核功能内推信息的发布内容是需要审核的,我在这里就大体可以分成三部分 基础审核(包括字数、不能包括可能导致页面混乱的代码出现等等) 敏感词审核(调用阿里云的敏感词检测API,也可以用其他的) 检测图片是否违规(抽取图片链接,检测是否合法) 初步想法: 创建抽象处理者 public interface ReviewHandler{ Result review(Article article);} 创建三个审核步骤的实现类(具体处理者),它们都继承抽象处理者,分别是 BaseReviewHandler、 SensitiveWordReviewHandler、ImageReviewHandler。三个类上均需要加上@Component,交由Spring进行管理,其中BaseReviewHandler上加了@Primary,表示当前这个类会被第一个调用。(因为三个类要依次审核 ...
拖拽排序功能的架构实现
在做疾病回访系统后台开发时,遇到一个很有意思的问题。问题是这样的,有多个模板题目,医生可以根据需要调整题目的先后顺序,从而更改题目的展示顺序。 对于这个需求,立刻就想到了以前做首页banner轮播图的管理后台。轮播图中每一张图有先后顺序之分,为了进行图片排序,在设计banner实体时,设计了一个 weight (权重)字段。然后,让运营人员给每张图填写1~500值,值越大,则排序越靠前。由于轮播图展示的图片有限(不超过5张),即使通过人工填值的方式管理顺序,也不是很麻烦。但是,这种填权重管理顺序的方式不适用于数据量较多的题目管理。那么,如何解决这种排序问题呢? 为了解决元素自定义排序问题,我想了很多解决办法。例如, 增加上移/下移功能,更改当前元素排序 填权重,或增减权重值 置顶排序 拖拽排序 最后,综合考虑了一下,认为第四种最符合日常操作的习惯。针对拖拽排序进行了后端方案设计。 需求描述 允许更改元素的排序; 允许新增数据,并更新现有排序; 允许删除数据,并更新现有排序。 解决办法方法一 全量更新元素位置法适用场景:排序元素数量较少 原理:每个元素拥有一个字段,表示元 ...
总结超10G大文件上传的Java方案
文件上传是一个非常常见的操作,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法,毕竟很少有人会忍受,当文件上传到一半中断后,继续上传却只能重头开始上传,所以我在网上学习并总结出了多种上传方案,这里对他们进行汇总 秒传概念通俗的说,把要上传的东西上传,服务器会先做MD5校验,如果服务器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器上的同一个文件,想要不秒传,其实只要让MD5改变,就是对文件本身做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5就变了,就不会秒传了。 核心逻辑A. 利用redis的set方法存放文件上传状态,其中key为文件上传的md5,value为是否上传完成的标志位, B. 当标志位true为上传已经完成,此时如果有相同文件上传,则进入秒传逻辑。如果标志位为false,则说明还没上传完成,此时需要再调用set的方法,保存块号文件记录的路径,其中key为上传文件md5加一个固定前缀,value为块号文件记录路径 分片上传概念分片上传,就是将所要上传的文件,按照一 ...
记录使用线程池优化的两种方式
采用CompletableFuture异步编程实现数据汇总传统的Future异步编程实现起来非常复杂,它需要实现FutureTask方法并实现Callable内部类,再结合Thread或者线程池的方式实现,获得返回值要调用FutureTask的get方法,他会阻塞后面的代码,但是如果后面的代码不依赖返回值的话,我们希望它们能以并行的方式去执行,那我们就能结合CompletableFuture去改造 它提供了两种异步任务: runAsync(),方法执行任务是没有返回值的 supplyAsync()方法执行任务则支持返回值 两种组合处理: anyOf返回跑的最快的那个future。最快的如果异常都玩完 allOf全部并行执行,如果需要获得返回值,需要配合thenApply,异常会抛出不影响其他任何任务 异步回调方法:不会阻碍后面的任务执行 whenComplete()没有返回值,且返回的CompletableFuture为任务结果,而非回调结果 handle()有返回值,且返回的CompletableFuture为回调结果 上面两个方法出现异常不会中断throwable:参数 ...
责任链模式的实际使用
最近认真学了一下设计模式的责任链模式,觉得把它用在项目的优化上,应该可以使代码变得更加优雅。 定义 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。将所有处理者形成一条链,在链中决定哪个对象能够处理请求,并返回结果,不能处理则继续向下传递请求。 组成 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。 优点将请求和处理分开,请求者不需要知道是谁处理的,处理者可以不用知道请求的全貌。 缺点 性能问题,每个请求从链头遍历到链尾,如果链比较长则性能低下。 调试问题,属于递归调用,调试不方便。 使用场景 在我的药源精鉴项目中,像一些需要过期处理的东西,比如,订单未支付过期处理,发 ...
盘点Mysql的一些优化手段
Mysql大家都不陌生,他是我们日常用到的最多的数据库了,但是对于它的优化,虽然大家都不陌生,但是总有的想不到,所以为了以后的开发做参考,我对它的优化手段进行了汇总。参考网上各种资料(本人均已做实践验证) 一般语句优化其实对于一般语句的优化,很多规范大家并不陌生,可就是在用的时候,无法遵从,所以在这里对这些进行汇总,以后温故而知新,可以养成一种良好的数据库编码习惯。 选择合适的数据类型及字符集使用合适的数据类型可以减少存储空间和提高查询速度。 例:对于布尔值使用 TINYINT(1) 而不是 CHAR(1) 比如你有一个字段是表示业务状态或者是类型。 CREATE TABLE users ( is_active TINYINT(1)); 对于仅存储英文的表,使用 latin1 而不是 utf8mb4。 CREATE TABLE messages ( content VARCHAR(255) CHARACTER SET latin1); 避免使用SELECT *仅选择必要的列,减少数据传输量。 例:避免 SELECT *,改用具体列名。 SELECT id, name, ...
分布式系统下订单业务解决方案
下单业务可能会出现的问题:1.超卖 2.数据一致性 3.超时 4.性能 业务流程图绘制:![lcl](C:\Users\28168\Pictures\Saved Pictures\UI10.31\lcl.png) 问题解决下面我们一一解决上面提出的订单业务的四个问题 1.超卖问题对于超卖问题,这里我采用了Redission分布式锁来解决,通过Redission锁定库存,从而避免了超卖问题 锁定库存的业务流程 什么是Redission?Redisson分布式锁解决分布式环境下并发安全问题,完全实现了juc的功能,不仅有锁,还都是分布式锁 Redisson是架设在Redis基础上的一个Java驻内存数据网格(ln-Memory Data Grid)。 Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务, ...
实现百万级数据从Excel导入到数据库
最近设计实现了从Excel中读取百万级数据并将其插入数据库的解决方案、主要为了应对给出了很多数据而且是以excel表格形式,怎么将这些数据既快又安全地导入到数据库。 场景分析首先分析一下 从Excel中读取百万级数据并将其插入数据库时可能遇到的问题: 内存溢出风险 加载如此庞大的Excel数据可能导致内存溢出,需要注意内存管理。 性能瓶颈 处理百万级数据的读取和插入操作可能很耗时,性能优化至关重要。 异常处理策略 读取和导入过程中会有各种潜在问题,我们需妥善处理各类异常情况。 问题分析内存溢出问题处理百万级数据,直接加载到内存中显然不现实。解决之道在于采用流式读取,分批处理数据。 在技术选型上,我选择了EasyExcel。它专为处理大数据量和复杂Excel文件进行了优化。EasyExcel在解析Excel时,不会将整个文件一次性加载到内存中,而是按行从磁盘逐个读取数据并解析。 性能问题针对百万级数据的处理,单线程显然效率低下。提升性能的关键在于多线程处理。 多线程应用涉及两个场景:一是多线程读取文件,另一个是多线程实现数据插入。这涉及到生产者-消费者模式,多线程读取并多线程 ...