依赖冲突的发现和解决
依赖冲突的发现 现象一:一个类的行为不按照预期,本来这个类应该是有这个方法的,但是引入一个新的依赖之后就开始报错找不到方法了,一般就是依赖冲突的时候 Maven 自己选择了一个不符合自己预期的依赖导致报错。 依赖冲突的解决使用 Maven helper 找到对应类所在 jar 的依赖都由谁导入,之后排除掉不符合自己预期的依赖即可。 一般直接在插件右键就可以 exclude
关于阅读源码
帮助文档是javadoc自动生成的,里面的内容都是源代码的注释有的东西,源代码是英文,文档有中文,可以文档和源码辅助一起看,更加清晰,看懂英语,也知道自己在哪个位置父类子类都有啥 有效读源码 5、解决方案。对于一些特定的问题,业界都是有一套成熟的解决方案的,一定要学到,这些是实打实在工作中会用到的。(举栗,分布式理论(事务,一致性算法,分布式锁),一致性Hash,负载均衡)还有就是。设计商品秒杀场景解决方案,缓存各种问题的解决方案,等等。。。 意义何在: 为什么这么写,设计模式 实现细节要画图 使用API时候的注意事项, 如何初始化 List、Map 及其 大小, 如何使用线程池设置合理,如何优雅使用锁, idea查看继承树https://jingyan.baidu.com/article/0bc808fc0f48661bd485b90c.html 源码查看(推荐)构建源码项目新建一个空的maven项目 将src.zip拷贝到项目的根目录,解压。 这样主要是为;了idea索引时间比较短,放在src里面索引时间太长了 注意同级目录: 设置源码为当前文件夹下的,不然不能...
从消息队列理解Pull与Push模型底层逻辑
在构建分布式消息系统时,我们面临的一个基本决策是确定数据流动的方向:消费者是从代理 (Broker) 拉取数据,还是由代理主动将数据推送给消费者。这一决策不仅影响系统的性能和效率,还决定了系统的架构和可扩展性。 推送 (Push) 模型的优势与局限 在 推送模型 中,数据流是由生产者主动向代理发送数据,随后代理根据预先设定的规则或策略,将数据推送给注册的消费者,这种模型的优点包括较低的延迟和实时性更强的数据传递。 然而,推送模型也有明显的局限性。 首先,它对网络带宽的要求较高,特别是在高并发的场景下,大量的小数据包频繁传输会导致网络拥塞。例如,消费者的消费能力为 10 条/s,而生产者生产能力为 100 条/s,此时会导致大量请求向下积压,当然,可以在 mq (Broker) 处进行消息堆积,或利用死信队列等机制进行退回,但是相应的,对于 Broker 的服务器压力也会显著增大。 其次,由于数据传输速率由代理控制,不同消费者之间的处理能力差异可能导致部分消费者无法及时处理接收到的数据,从而造成系统资源浪费或系统过载。 特别是当消费者的处理速度低于生产者的生...
主流中间件选型手册(1)--注册中心
为什么理解注册中心的必要性,就需要了解软件架构的发展历程。 系统架构的发展历程 为什么需要注册中心上面的微服务架构采用直连的方式,每一个机器都需要维护更新自己需要连接的机器的IP,将来地址出现变更,还需要及时更新。在集群内部的节点越来越多的时候,开发者管理起来将会非常混乱。此时加入注册中心,就无需将消费者和服务提供者绑定了,提供者宕机不会对消费者产生直接的影响,所有的机器只需要和注册中心去交互。服务方与注册中心之间通过“心跳”机制进行监控。实现服务的自动注册、发现、状态监控: 是什么注册中心一般会存放机器IP和URL之间的映射,并且在其客户端一般都会附带负载均衡的功能帮助用户开箱即用调用其他机器的服务。还会通过心跳机制实现服务的自动注册、发现、状态监控。 怎么用开源中间件zookeeper简单介绍最初是Hadoop的子项目,用来管理分布式中的集群。一般用作配置中心、注册中心、分布式锁 简单使用安装以及命令行的使用:https://juejin.cn/post/7025887917243383844 常见的客户端:Zookeeper Java客户端、Apache Curator...
代理模式Proxy
问题提出:benchMark 性能测试,不修改原来代码,记录代码的运行时间: **继承实现:**类爆炸 **手动组合:**自己使用代理类包装,代理类里面调用被代理对象,附加上自己的事情。 实现同一个接口可以实现代理的嵌套,当需要实现多个代理功能的时候 限制就是要实现同一个接口 全能代理:不同接口,解耦,动态代理,运行时候生成。 **java.lang.reflect.Proxy **:通过反射getClass(Loader),不需要读取源码,只需要二进制字节码就得到属性和方法。 被代理类需要有接口:代理遵循接口才能伪装为服务的对象,让外界调用接口即可,我们负责替换 cglib:底层也是asm。但是其实是生成了一个被代理类的子类,所以当一个类是final的时候,是不可以使用这个来实现代理的 asm:甚至可以代理final,因为直接修改二进制字节码,所以随意 注意字节码class文件是二进制的,使用IDE打开的时候是显示反编译之后的代码,其实不是文件真正存放的内容 静态代理–自己包装被包装和包装类都要实现一样的接口, 构造的时候都使用接口作为形参,传递实参的时...
内存泄漏与SWAP
内存泄漏如何发生没正确回收分配后的内存,导致了泄漏。 访问的是已分配内存边界外的地址,导致程序异常退出 用户空间内存包括多个不同的内存段,比如只读 段、数据段、堆、栈以及文件映射段等。这些内存段正是应用程序使用内存的基本方式。 只读段、数据段、栈不会泄漏在程序中定义了一个局部变量,比如一个**整数数组 int data[64]** ,就定义了 一个可以**存储 64 个整数的内存段。由于这是一个局部变量,它会从内存空间的栈中分配内存。栈内存由系统自动分配和管理。一旦程序运行超出了这个局部变量的作用域,栈内存就会被 系统自动回收,所以不会产生内存泄漏的问题。** 只读段,包括程序的代码和常量,由于是只读的,不会再去分配新的内存,所以也不会产 生内存泄漏。 数据段,包括全局变量和静态变量,这些变量在定义时就已经确定了大小,所以也不会产 生内存泄漏。 堆和文件映射可能会泄漏事先并不知道数据大小,所以你就要用到标准库函数** malloc() ,在程序中动态分配内存。这时候,系统就会从内存空间的堆中分配内存。堆内存由应用程序自己来分配和管理。除非程序退出,这些堆内存并不会被系统自动释放,...
内存知识总结
虚拟内存与多级页表对普通进程来说,能看到的其实是内核提供的虚拟内存,这些虚拟内存还需要通过页表,由系统映射为物理内存。 当进程通过 malloc() 申请虚拟内存后,系统并不会立即为其分配物理内存,而是在首次访 问时,才通过缺页异常陷入内核中分配内存。 内存缓存为了协调 CPU 与磁盘间的性能差异,Linux 还会使用 Cache 和 Buffer ,分别把文件和磁 盘读写的数据缓存到内存中。 内存回收一旦发现内存紧张,系统会通 过三种方式回收内存: 基于 LRU(Least Recently Used)算法,回收缓存; 基于 Swap 机制,回收不常访问的匿名页; 基于 OOM(Out of Memory)机制,杀掉占用大量内存的进程。 直接内存回收:缓存回收和 Swap 回收实际上都是基于 LRU 算法,也就是优先回收不常访 问的内存。LRU 回收算法,实际上维护着 active 和 inactive 两个双向链表,其中: active 记录活跃的内存页; inactive 记录非活跃的内存页。 越接近链表尾部,就表示内存页越不常访问。这样,在回收内存时,系统就...
单例模式完全版
应用资源管理器 属性管理器 多例是为了存储数据的,单例是为了共享可以减少资源消耗 饿汉式–JVM保证线程安全(简单推荐)因为JVM可以保证每个类只加载一次,所以设置为static就可以保证对象只会被new一次,static是在加载链接初始化中的初始化就会赋值的,只执行一次。 多线程都没关系 但是用到与否,类加载就已经实例化 12345678910111213141516171819202122232425262728package com.deltaqin.designPattern.d01_singleton;/** * @author deltaqin * @date 2021/3/26 1:39 下午 */public class Single01 { private static final Single01 INSTANCE = new Single01(); public static Single01 getInstance() { return INSTANCE; } public void m(...
分布式锁最佳实践
在单体的应用开发场景中涉及并发同步的时候,大家往往采用 Synchronized(同步)或者同一个JVM内Lock机制来解决多线程间的同步问题。在分布式集群工作的开发场景中,就需要一种更加高级的锁机制来处理跨机器的进程之间的数据同步问题,这种跨机器的锁就是分布式锁。 超卖问题复现现象存在如下的几张表: 商品表 订单表 订单item表 :::danger 商品的库存为1,但是并发高的时候有多笔订单。 ::: 错误案例一:数据库 update 相互覆盖直接在内存中判断是否有库存,计算扣减之后的值更新数据库,并发的情况下会导致相互覆盖发生: 123456789101112131415161718192021222324252627@Transactional(rollbackFor = Exception.class)public Long createOrder() throws Exception { Product product = productMapper.selectByPrimaryKey(purchaseProductId); ...
原型、克隆Prototype模式
复制已有对象, 而又无需使代码依赖它们所属的类。 下面不是规范的克隆,这是复制浅克隆(新属性指向原对象),深克隆 java自带,需要实现标记接口,重写clone方法。一个对象属性多指定起来麻烦会使用,不会比new有多的好处, JDK 中的原型克隆注意字符串不需要,因为intern得到是常量池里面的同一个字符串,克隆修改只会使得变量指向其他的常量 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758package com.deltaqin.designPattern.d16_prototype;/** * 深克隆 * * @author deltaqin * @date 2021/3/27 3:20 下午 */public class CloneDemo { public static void main(String[] args) throws Exception { Per...