2022学习笔记(持续更新)

1、hashMap为什么使用数组+链表?

为什么使用数组?
速度:读、写,最快的是数组, 数组快是快,但是需要知道读、写的索引,时间复杂度是O(1),对于一般的插入、删除操作,涉及到数组元素的移动,平均时间复杂度这变为O(N),HashMap中数组的下标是通过KEY.hashCode()%数组长度得到的,但是这种方法会造成哈希碰撞,那么就有了链表
为什么使用链表?
为了解决数据的KEY产生哈希碰撞后将原有的数组下标对应的值直接替换,那么这个时候为了解决这个问题就在产生哈希碰撞后,下标相同的KEY就会被串成链表结构,插是从头插,不是从尾,从头插时间复杂度为O(1),从尾插为O(N),这个链表是单向列表, 链表的新增,删除操作在查找到操作位置后,只需要处理节点间的引用即可,时间复杂度为O(1),但是查找操作则需要遍历链表中所有节点逐一比对,时间复杂度为O(N),这里的查询的时间复杂度为O(N)且遍历所有元素,数组变成链表是因为哈希碰撞的hashCode值都是一样的,那么对应的索引也是一样的,所有还要一个KEY取出来对比,所以也就有了遍历这么一说;这样的话链表过长性能会比较低,那么为了解决性能问题,JDK1.8后就引用了红黑树
为什么使用红黑树?
为了解决链表过长性能低的问题,红黑树是一种接近于平衡二叉树,但不是绝对平衡,逻辑上是个树形结构,是一个有序的结构,在每个节点上增加一个存储位,表示节点的颜色,可以是Red或者Black,通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,而是接近平衡的,支持查找,插入,删除,其平均时间复杂度最坏为O(logn);这里解释一下(红黑树确保没有任何一条路径会比其他路径长出两倍)
1、如果一个节点是红色的,则它的子节点必须是黑色的。也就是一条路径上没有两个连续的红色节点;

2、对于任一节点而言,其到叶节点树尾端NULL指针的每一条路径都包含相同数目的黑节点。

因为黑色节点数量相同,最多黑色之间有相同数量的红色节点.所以没有一条路径会比其他路径长出俩倍

2、为什么使用双亲委派?

主要为了安全,次要是在四个加载器中加载过一次了就不需要再加载了
在这里插入图片描述

3、线程池底层的三个重要参数是什么

corePoolSize(5) 核心线程数
workQueue(2) 阻塞队列
maximumPoolSize 最大线程数(6)
unit:这个用来指定keepAliveTime(超时时间)的单位,比如秒:TimeUnit.SECONDS
keepAliveTime (30分钟)空闲线程最大存活时间
RejectedExcutionHandlder: 当workQueue已经满了,并且线程池线程数已经达到maximumPoolSize,将执行拒绝策略
AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
DiscardPolicy:丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。
DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务。
CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

4、springcloud 组件有哪些?

Eureka service:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号
Eurake Client:负责将这个服务的信息注册到Eureka Server中

Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求。Spring Cloud引入 Feign并且集成了Ribbon实现客户端负载均衡调用。解决了什么问题?封装了Http调用流程,更适合面向接口化的编程习惯
与OpenFeign的区别
1、依赖不同。
2、Feign直接加在接口上并且不支持SpringBoot注解。OpenFeign支持@RequestMapping("/demo/test")这种注解。
OpenFeign:最核心的作用是为 HTTP 形式的 Rest API 提供了非常简洁高效的 RPC 调用方式。

Ribbon:负载均衡,会帮你在每次请求时选择一台机器,均匀的把请求分发到各个机器上
在这里插入图片描述
Hystrix:解决服务雪崩,隔离、熔断以及降级的一个框架
在这里插入图片描述
zuul:微服务网关,这个组件是负责网络路由的。
网关会根据请求中的一些特征,将请求转发给后端的各个服务。
而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全,等等
在这里插入图片描述

5、服务与服务之间怎么调用?

在这里插入图片描述

6、Redis的AOF与RDB

RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照。

AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。

Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

RDB的优点:是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。
缺点:RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。
如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。

AOF的优点
AOF 的默认策略为每秒钟同步一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据(同步会在后台线程执行,所以主线程可以继续努力地处理命令请求)
缺点:相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。关闭同步可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。

7、Eureka崩了后,服务之间还能调用么?怎么处理?

可以调用,在启动消费者和提供者的时候,eureka注册中心是正常运行的,因此可以将各个消费者和提供者可以正常订阅。当eureka突然宕机的时候,各个提供者和消费者都已经保存有相互间的服务名称与ip映射,所以相互访问没有问题。

在eureka宕机的情况下,消费者或者提供者服务重启后,消费者是否可以继续访问提供者?
在eureka宕机未启动的情况下,当消费者重新启动后,无法从eureka中拉取其他服务的映射信息,因此消费者是无法再访问提供者的。不过,当提供者重新启动后,由于消费者还继续保存着与提供者之间的映射信息,而且提供者的信息并未发生改变,因此消费者还是可以继续访问提供者的。

在eureka宕机的情况下,服务之间在何种情况下无法继续进行相互访问?
所有服务全部停止,再重新启动除eureka之外的服务;
修改消费者或提供者IP,端口,服务名称等映射信息的情况下。

8、设计模式

单例模式:饿汉模式:先把对象创建好,等我要用的时候直接拿来用。
这种模式是最简单最省心的,不足的地方是容易造成资源上的浪费
在这里插入图片描述
懒汉模式:先不创建类的对象实例,等需要的时候再创建。
懒汉模式解决了饿汉模式可能引起的资源浪费问题,因为这种模式只有在用户要使用的时候才会实例化对象。但是这种模式在并发情况下会出现创建多个对象的情况。
在这里插入图片描述
因为可能出现外界多人同时访问SingleCase.getInstance()方法,这里可能会出现因为并发问题导致类被实例化多次,所以懒汉模式需要加上锁synchronized (Singleton.class) 来控制类只允许被实例化一次。
但加锁的方式会严重影响性能。
解决方案一:双重检查加锁(DCL)
在这里插入图片描述
但是DCL在并发情下也会存在一个问题,因为Jvm指令是乱序的;
new的时候 CPU指令主要有三步,指令1:申请分配对象内存,指令2:调用构造器初始化对象属性,指令3:构建对象引用指向内存。乱序可能变成132
可以使用volatile关键字解决乱序问题,volatile关键字可以保持线程可见性,禁止指令重排序

解决方案二:用内部类实现懒汉模式
在这里插入图片描述
当外部类被访问时,并不会加载内部类,所以只要不访问SingletonHoler 这个内部类, private static Singleton singleton = new Singleton() 不会实例化,这就相当于实现懒加载的效果,只有当SingletonHoler.singleton 被调用时访问内部类的属性,此时才会将对象进行实例化,这样既解决了饿汉模式下可能造成资源浪费的问题,也避免了懒汉模式下的并发问题。

工厂模式
主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的 解耦
简单工厂模式:需求,都在同一个类中
工厂方法模式:根据不同的需求,创建多个不同的类。不适合比较大的项目中
抽象工厂模式:提供一个创建一系列相关或相互依赖的对象接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例

9、springboot使用的设计模式

singleton:单例的bean只有第一次创建新的bean 后面都会复用该bean,所以不会频繁创建对象。
prototype:原型的bean每次都会新创建

单例bean的优势:
1、减少了新生成实例的消耗 新生成实例消耗包括两方面,首先,Spring会通过反射或者cglib来生成bean实例这都是耗性能的操作,其次给对象分配内存也会涉及复杂算法
2、减少jvm垃圾回收 由于不会给每个请求都新生成bean实例,所以自然回收的对象少了
3、可以快速获取到bean 因为单例的获取bean操作除了第一次生成之外其余的都是从缓存里获取的所以很快
单例bean的劣势:不能做到线程安全

Spring 为啥把bean默认设计成单例?为了提高性能!1.少创建实例2.垃圾回收3.缓存快速获取

10、spring中的Bean生命周期

1、创建bean,并且准备一些附属方法
首先,bean会由程序来调用其构造函数进行初步构造,
然后,通过依赖注入方式对bean的各属性,或者说各setter方法进行注入信息。 创建bean已完成
还会存在几个接口的实现
BeanNameAware 设置Bean的name
BeanFactoryAware 将BeanFactory设置给Bean
ApplicationContextAware spring将当前Bean引入到应用上下文中,就是说可以通过ApplicationContext获取到当前的Bean
InitializingBean 执行afterPropertiesSet方法,配置的加载
init Bean的初始化
BeanPostProcessor的后置处理方法,即创建完成

2、使用bean
业务逻辑上的使用

3、销毁bean
第一时间执行DisposableBean接口的destroy方法,再执行Bean自定义的destroy方法

11、Java8新特效

中间操作:filter、distinct、limit、skip、map、flatMap、sorted
在这里插入图片描述

最终操作:anyMatch、allMatch、noneMatch:返回Boolean类型
findAny:并行随机获取 parallelStream(并行流)
findFirst:只取第一个
foreach:遍历
collect:toList 返回一个数组、toSet 返回一个去重数组、toMap 返回一个map
在这里插入图片描述

12、MySQL索引

校验SQL语句是否使用了索引方式为:在SQL语句前面使用explain关键字
(1):like以%开头索引无效,当like以&结尾,索引有效。
(2):or语句前后没有同时使用索引,当且仅当or语句查询条件的前后列均为索引时,索引生效。
(3):组合索引,使用的不是第一列索引时候,索引失效,即最左匹配规则。
(4):数据类型出现隐式转换,如varchar不加单引号的时候可能会自动转换为int类型,这个时候索引失效。
(5):在索引列上使用IS NULL或者 IS NOT NULL 时候,索引失效,因为索引是不索引空值得。
(6):在索引字段上使用,NOT、 <>、!= 、时候是不会使用索引的,对于这样的处理只会进行全表扫描。
(7):对索引字段进行计算操作,函数操作时不会使用索引。
(8):当全表扫描速度比索引速度快的时候不会使用索引。
什么是索引?
索引其实就是一种数据结构,能够帮助我们快速的检索数据库中的数据。
索引具体采用那种数据结构呢?
常见的mysql主要有两种结构:hash索引和B+Tree索引,我们使用的是innodb引擎,默认的是B+树。
既然提到了InnoDB使用户的B+树的索引模型,那么你知道为什么采用B+树吗?这和Hash索引比较起来有什么缺点吗?
因为hash索引底层是哈希表,哈希表是一种以key-value存储数据的结构,所以多个数据在存储关系上是完全没有任何顺序关系的,所以,对于区间查询是无法直接通过索引查询的,就需要全表扫描。所以,哈希索引只适用于等值查询的场景。而B+树是一种多路平衡查询树,所以他的节点是天然有序的(左子节点小于父节点,父节点小于右子节点),所以对于范围查询的时候不需要做全表扫描。

13、垃圾回收器

1.8默认 Parallel Scavenge + Parallel Old
在这里插入图片描述
在这里插入图片描述

14、内存溢出 如何查询代码问题

第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)

第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。

第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

重点排查以下几点:
  1.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
  2.检查代码中是否有死循环或递归调用。

3.检查是否有大循环重复产生新对象实体。

4.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中 数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

5.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

第四步,使用内存查看工具动态查看内存使用情况

15、MySQL存储过程

SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。

16、springboot的启动流程

17、循环依赖引用怎么处理

18、set是如何去重的

1、对于有值特性的,set集合可以直接判断进行去重
2、对于引用数据类型的类对象:
set集合会让两两对象,先调用自己的hashCode()方法得到彼此的哈希值(所谓的内存地址),然后比较两个对象的哈希值是否相同,如果不相同则直接认为两个对象不重复。
如果哈希值相同,会继续让两个对象进行 equals比较内容是否相同,如果相同,认为真的重复了,如果不相同则不重复。

19、jfinal原理

在这里插入图片描述

20、Redis存储原理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值