java基础总结-持续更新

ArrarList和linList
arraylist:数组结构,查询快,增删慢
linkList:双向链表结构,查询慢,增删快
TreeMap和hashMap的区别
1、HashMap是通过hashcode()对其内容进行快速查找的;HashMap中的元素是没有顺序的;

TreeMap中所有的元素都是有某一固定顺序的,如果需要得到一个有序的结果,就应该使用TreeMap;

2、HashMap和TreeMap都不是线程安全的;

3、HashMap继承AbstractMap类;覆盖了hashcode() 和equals() 方法,以确保两个相等的映射返回相同的哈希值;

 TreeMap继承SortedMap类;他保持键的有序顺序;

4、HashMap:基于hash表实现的;使用HashMap要求添加的键类明确定义了hashcode() 和equals() (可以重写该方法);为了优化HashMap的空间使用,可以调优初始容量和负载因子;

 TreeMap:基于红黑树实现的;TreeMap就没有调优选项,因为红黑树总是处于平衡的状态;

5、HashMap:适用于Map插入,删除,定位元素;

 TreeMap:适用于按自然顺序或自定义顺序遍历键(key);

6.hashMap区分key的字母大小写(hashCode方法),treeMap不区分key的大小写

hashMap的扩容:初始容量为16,扩容因子为0.75,当map容量达到12时,map扩容2倍,长度达到32 (预知map的大小设置值可以增强性能,减少hash碰撞扩容)(resize方法进行扩容)
hashMap的底层是链表结构,当链表长度超过8的时候转化为红黑树结构,阈值为6的时候结构恢复为链表结构(jdk1.8版本之后)
hashMap的get:将key通过hash方式转化为hash值,通过equal方式寻找链表上的符合情况的索引处的对应key的entry返回value
hashMap的put:首先进行为null判断,为null调用putForNullKey方法,否则调用hash方法计算出hash值,通过equal方法寻找链表上对应hash值的索引,索引出的是否有entry,有的话比较entry的key,若相同,则覆盖之前的value,不相同则在索引头部增加entry

基础知识:
Collections和Collection的区别:Collections是一个帮助类,内含集合元素的排序,大小 ,搜索的静态方法;Collection是所有集合类的实现的父接口,继承它的接口主要有List和Set,提供删除,插入等操作
多线程的应用
类:ThreadPoolTaskExecutor(底层实现runable接口,callable是有返回值的)ThreadPoolExecutor (2个正常代码中使用的多线程配置的类)
线程的五种状态:new(新建) runnable(可运行)running(运行中) blocked(阻塞:死锁或者sleep waiting(无限等待) timed waiting(有限等待) terminated(结束)
线程池参数:1.核心线程数 2.总线程数 3.队列 4.空闲线程存活时间 5.拒绝策略(a.直接丢弃任务 b.直接丢弃任务后抛出异常 c.放弃最早进入队列的任务,尝试将新任务添加到队列 d.直接执行任务,除非线程shutdown)
阻塞线程:业务实现,在线程中没有数据处理时,阻塞线程,防止线程一直调用cpu而没有业务实现(sleep方法)
多线程实际应用对象:ThreadPoolTaskExecutor(任务级别线程对象) ThreadPoolExecutor(自定义线程对象,常用)
常用场景:线程池和redis搭配实现多线程应用,处理大数据并发,同时实现补偿重试机制(将失败数据存储redis,多线程轮询redis中的数据)
注意:若存在全量数据的话,需要考虑线程安全,此时尽量不使用redis,使用redis分布式锁实现
多线程下的线程安全:synchronized和ReentrantLock的lock锁可以实现线程安全,lock相对于synchronized来说效率更高,但是需要手动调用释放锁的方法,不然会出现死锁,Lock是一个接口,synchronized是一个关键字,lock可以判断是否获得锁
synchronized使用:在多线程开启后的方法执行中使用同步代码块或者同步方法
lock锁使用:在线程中,先尝试获取锁,获取锁后执行业务代码,然后在finally中释放锁,不然会出现死锁
Java锁机制
公平锁和非公平锁(实现手写)
重入锁和不可重入锁(实现手写)
死锁和解开死锁(实现手写)
jvm内存模型
堆 由线程共享,存放 new 出来的对象,是垃圾回收器的主要工作区域。
栈(本地方法栈和虚拟机栈) 线程私有,分为 Java 虚拟机栈和本地方法栈,存放局部变量表、操作栈、动态链接、方法出口等信息,方法的执行对应着入栈到出栈的过程。
方法区 线程共享,存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等信息,JDK 1.8 中方法区被元空间取代,使用直接内存。
jvm调优:经过调整jvm的堆内存大小,合理分配新生代和老年代的内存,减少GC,系统性能得到优化(当新时代的内存满时Java内部自动执行GC),重点是避免在代码中执行人工GC
垃圾回收算法
Mark-Sweep(标记-清除)算法 标记需要回收的对象,然后清除,会造成许多内存碎片。
Copying(复制)算法 将内存分为两块,只使用一块,进行垃圾回收时,先将存活的对象复制到另一块区域,然后清空之前的区域。
Mark-Compact(标记-整理)算法(压缩法) 与标记清除算法类似,但是在标记之后,将存活对象向一端移动,然后清除边界外的垃圾对象。
Generational Collection(分代收集)算法 分为年轻代和老年代,年轻代时比较活跃的对象,使用复制算法做垃圾回收。老年代每次回收只回收少量对象,使用标记整理法。
典型垃圾回收器
CMS
简介 以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是 Mark-Sweep 算法。
场景 如果你的应用需要更快的响应,不希望有长时间的停顿,同时你的 CPU 资源也比较丰富,就适合适用 CMS 收集器。
垃圾回收步骤
初始标记 (Stop the World 事件 CPU 停顿, 很短) 初始标记仅标记一下 GC Roots 能直接关联到的对象,速度很快;
并发标记 (收集垃圾跟用户线程一起执行) 并发标记过程就是进行 GC Roots 查找的过程;
重新标记 (Stop the World 事件 CPU 停顿,比初始标记稍微长,远比并发标记短) 修正由于并发标记时应用运行产生变化的标记。
并发清理,标记清除算法;
缺点
并发标记时和应用程序同时进行,占用一部分线程,所以吞吐量有所下降。
并发清除时和应用程序同时进行,这段时间产生的垃圾就要等下一次 GC 再清除。
采用的标记清除算法,产生内存碎片,如果要新建大对象,会提前触发 Full GC 。
G1
简介 是一款面向服务端应用的收集器,它能充分利用多 CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型,即可以设置 STW 的时间。
垃圾回收步骤 1、初始标记(stop the world 事件 CPU 停顿只处理垃圾); 2、并发标记(与用户线程并发执行); 3、最终标记(stop the world 事件 ,CPU 停顿处理垃圾); 4、筛选回收(stop the world 事件 根据用户期望的 GC 停顿时间回收)
特点
并发与并行 充分利用多核 CPU ,使用多核来缩短 STW 时间,部分需要停顿应用线程的操作,仍然可以通过并发保证应用程序的执行。
分代回收 新生代,幸存带,老年代
空间整合 总体看是采用标记整理算法回收,每个 Region 大小相等,通过复制来回收。
可预测的停顿时间 使用 -XX:MaxGCPauseMillis=200 设置最长目标暂停值。

cms回收器执行步骤
1、初始标记:GC roots 可以理解为对象指向的标记
2、并发标记: GC roots Tracing 可以理解为 通过初始标记找到了要删除的对象 也就是堆中的指向对象
3、重新标记: 可以理解为重新执行了一遍 初始标记 和 并行标记 产生标记记录
4、删除标记:标记删除发进行并发删除
优点:并行执行,低停顿
缺点:
1、不停顿耗线程,耗内存,整体效率低
2、标记清除法会产生垃圾碎片 容易FGC
3、会产生浮动垃圾容易FGC
g1回收器:
1、初始标识:GC roots 可以理解为对象指向的标记 并且更改tame值出发并发标记
2、并发标记:GC roots Tracing 可以理解为 通过初始标记找到了要删除的对象 也就是堆中的指向对象
3、最终标记: 可以理解为重新执行了一遍 初始标记 和 并行标记 产生标记记录 将标记记录存到remember set log中,然后在合并到 remember set中,通过remember set 来管理对象的引用
4、筛选回收:通过Region区块对回收价值和成本进行排序,根据用户所希望的GC时间进行回收。
优点:
1、空间整合:g1使用Region独立区域概念,g1利用的是标记复制法,不会产生垃圾碎片
2、分代收集:g1可以自己管理新生代和老年代
3、并行于并发:g1可以通过机器的多核来并发处理 stop - The - world停顿,减少停顿时间,并且可不停顿java线程执行GC动作,可通过并发方式让GC和java程序同时执行。
4、可预测停顿:g1除了追求停顿时间,还建立了可预测停顿时间模型,能让制定的M毫秒时间片段内,消耗在垃圾回收器上的时间不超过N毫秒
最大的区别是出现了Region区块概念,可对回收价值和成本进行排序回收,根据GC期望时间回收,还出现了member set概念,
将回收对象放入其中,避免全堆扫描

常用注解:
资源加载(跟随项目启动执行的方法):@PostConstruct:类加载时执行方法加载资源或执行方法内的业务代码
Controller:@PathVariable(header) @RequestParam(get) @RequestBody(post) @RestController @CrossOrigin

Service:@Servier  @Slf4j  @Transactional

Mapper:@ Repository 

配置类:@Configuration   @Bean   @Autowired  @Resource    @NoArgsConstructor  @AllArgsConstructor   @Data  @RefreshScope(动态获取nacos配置信息)

功能性:@Scheduled   @SneakyThrows   	@PostConstruct   @FeignClient

启动类:@SpringBootApplication	@EnableFeignClients

注解分析:@Bean @Resource @Qualifire
@Bean是属于spring的注解,根据类型选择需要注入的类,可以作用在类,方法,构造方法上,当存在相同类型时,可以组合@Qualifire注解指定注入的名称(选择性注入)
@Resource属于j2ee的注解,优先根据名称选择注入的类,若根据名称寻找不到,再进一步根据类型选择注入
其他技能:
execel的导入导出
rabbit
保证消息不丢失:消息提供者:confirm模式,保证消息经过交换机到达队列
队列:持久性队列和持久性消息,即使rabbit服务宕机也能恢复消息
消费者:ACK确认模式,手动确认
重复消费:幂等性
死性队列: 实现延迟队列
延迟队列:订单系统关闭
特性:削峰,解耦,异步
nginx:反向代理
redis:主要消耗内存资源
数据类型:string list set hash zset
持久化机制:RDB:隔段时间进行数据持久化保存到硬盘,类似快照,容易发生数据丢失
AOF:一直将所有数据持久化,redis重启后能够根据日志恢复所有数据文件,在大数据情况下性能较差,允许RDB和AOF同时开启,优先恢复AOF的数据
哨兵机制:主从节点的切换,保证集群的健壮性,某个节点故障,从节点替换故障主节点,同时通知其他主节点替换信息,主节点恢复后重新变更为主节点
删除策略:定时过期:token的应用 惰性过期:访问key时清除,验证码的一次校验的应用 定期清除:类似定时任务,隔段时间扫描清除过期的key
主从模式
集群:Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。通过算法决定key的存放节点
问题处理:缓存雪崩(大量缓存过期,直接访问数据库层面),缓存击穿(直接访问数据库层面) ,缓存穿透(缓存和数据库中都不存在的数据)
redis队列和mq队列的对比:redis无法保证消息的不丢失,但是mq可以进入手动确认模式,消费失败后重新进入队列,redis的主从模式目前没有实现故障转义,mq几圈使用的是内存节点不会出现这种问题,redis直接将实例持久化到磁盘,mq可以选择消息和队列是否持久化,性能上mq的也是占优势的,同事redis不提供负载均衡,但是mq可以自行实现
选择redis队列时考虑的是代码的轻量和数据的重要性,相比于mq来说,redis实现队列是轻量的
Redis:轻量级,高并发,延迟敏感
即时数据分析、秒杀计数器、缓存等

RabbitMQ:重量级,高并发,异步
批量数据异步处理、并行任务串行化,高负载任务的负载均衡等

theamlife
freemarker
mysql
索引:聚簇索引与非聚簇索引
都使用 B+ 树作为数据结构
聚簇索引中数据存在主键索引的叶子结点中,得到 key 即得到 data ;非聚簇索引的数据存在单独的空间。
聚簇索引中辅助索引的叶子结点存的是主键;非聚簇索引中叶子结点存的是数据的地址;
聚簇索引的优势是找到主键就找到数据,只需一次磁盘 IO ;当 B+ 树的结点发生变化时,地址也会发生变化,这时非聚簇索引需要更新所有的地址,增加开销。
索引类型:
1.普通索引(INDEX)
2.唯一索引(UNIQUE)
3.主键索引(PRINMARY KEY)
4.组合索引(INDEX)
5.全文索引(FULLTEXT)
索引的优缺点:
优点:1.通过唯一索引的创建,保证数据的唯一性 2.加快数据的检索,避免了全表扫描 3.加速表之间的关联连接 4.加速分组和排序查询的时间
缺点: 1.索引的创建和维护需要时间,时间长度跟随数据量的大小增加而增加 2.索引占用物理空间 ,降低增删改的效率,索引的删除需要动态维护
创建索引的sql: Alert table ‘user_table ’ add INDEX index_name(‘id’) 增加普通索引
sql:增删改查,左右内连接,explain使用,group by ,order by (d是降序,a是升序)
引擎:InnoDB,myisam
事务概念:数据库操作的最小操作单元,它的执行要么整体执行,要么都不执行,是不可再分割的工作逻辑单元
4大事务特性:一致性,持久性,原子性,隔离性
4大隔离级别:读未提交 读已提交 可重复读(mysql默认的级别) 可串行话
4大问题:脏读 丢失修改 不可重复读 幻读
搜索引擎的比较:innordb 和myisam :5.7后的版本默认引擎是innordb,具有事务管理和支持外键的优势,然而myisam保持变量记录了整表的行数,innoDB则会出现全表扫描,innodb不支持全文搜索,而Myisam支持,Innodb支持表,行级所,而Myisam支持表级所
在选择搜索引擎的时候,若当前表只有查询的操作的话建议Myisam,有读有写的话就建议Innordb
sql执行顺序 :
from
join
on
where
group by(开始使用select中的别名,后面的语句中都可以使用)
avg,sum…
having
select
distinct
order by
limit
mybatis:
常用标签:
mybatisplus:函数式编程,仅适用于单表操作
canal:数据同步工具,版本1.1.4,可以使用组件实现直接跨服务同步表数据
es(将数据库中的数据同步到es中):对应项目data-center的vehicle中
同步流程:封装es对象,定义索引名称,查询数据库将数据封装后转化为es对象,调用es方法插入数据到es中
查询方式:分词
集成Lucene
核心点:索引(index),文档类型(type),文档(document),字段(filed)
linux(tail cat grep cop mkdir ls cd vim qw rm )
seata(分布式事务控制)
短信服务调用
单点登录的应用:使用jwt实现token的颁发和在网关的解析
应用:根据jwt官网引用和封装jwtHelper工具类,内含token生成和解析token的方法
refresh token的实现:延长过期时间和刷新角色
拦截器
文件上传
序列化和反序列化
握手协议
Lambda
springboot五大组件: Eureka(注册中心): 心跳机制 Ribbon(负载均衡):轮询 权重 随机 Hystrix(熔断器): 服务降级 隔离策略 :信号量隔离,线程隔离,线程隔离会造成请求参数的丢失,二次转发 Confige(配置中心) Gateway(网关)(GlobalFilter,Ordered):鉴权 拦截器
keycloak:认证授权管理解决方案 集成OAuth2,实现单点登录
微信支付调用:回调方法,返回支付结果 api入参:xml格式,需要json转xml格式
redis分布式锁:redissonClient的应用 实际应用
框架信息
spring:IOC+AOP(主要的是IOC的,实现了代码的解耦)
IOC:控制反转,将类的管理权交给spring容器来管理
AOP:Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
spring的事务管理
七大传播机制;1.有事务抛异常 2.有事务加入事务 3.有事务不作处理 4.没事务新建事务 5.嵌套事务 6.没事务抛异常
事务作用范围:
Bean的生命周期:1.Bean实例化 2.Bean属性注入 3.初始化实例 4.使用Bean 5.销毁Bean
SpringMVC的工作流程:1.前端请求到 :DispatcherServlet 2.DispatcherServlet根据请求信息调用HandlerMaping映射到对应的控制器(Handler)3.解析到Handler后由对应的HandlerAdapter(适配器)适配后台的处理器处理业务 4.Handler根据业务返回的数据体给到DispatcherServlet ,DispatcherServlet 再将返回的数据model交给View渲染后返回给前端页面
工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
Spring使用到的设计模式:
代理设计模式 : Spring AOP 功能的实现。
单例设计模式 : Spring 中的 Bean 默认都是单例的。
模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
适配器模式 : Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller
spring boot:核心注解:@SpringBootApplication (@Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合) @Conditional(获取所有需要自动装配的类)
加载步骤:1.判断自动装配开关是否开启 2.实现ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,获取符合条件的类 3.自动装配所有的配置类(加载配置文件) 4.@ConditionalOn 注解筛选符合条件的配置类
限流:
令牌桶算法:实现使用google的guava工具包,启用多线程获取令牌
漏桶算法:
熔断器的降级和熔断策略实现限流
netty

经典兜底方式和性能优化方式:为减少线上主线程的IO产生,将需要进行sql写入或更新的数据丢入到redis中,在另起一个任务,在任务中采用多线程的方法从redis中获取获取,获取后的数据可以再起多线程进行sql执行或者不执行,若已经执行完成则移除redis中的数据,若出现异常则重新放入redis中
redis队列的左进右出,采用了redis的队列存储类型,类似于MQ的消息队列样

面试点:
1.MVC和Spring boot的区别
mvc只是一个web框架,通过DispatcherServlet ,映射器,控制器和适配器实现页面,而spring boot类似于spring和spring mvc的结合,简化了配置文件,对于开发者来说,开发更加简洁,内嵌tomcat也是与mvc的最大区别

2.多线程中sleep和wait方法的区别
1、sleep是Thread的静态方法,wait是Object的方法,任何对象实例都能调用。
2、sleep不会释放锁,它也不需要占用锁。wait会释放锁,但调用它的前提是当前线程占有锁(即代码要在synchronized中)。
3、它们都可以被interrupted方法中断。
4.sleep是设置线程不会去参与cpu的占用竞争,不会去占用锁和释放锁,而wait是指释放占用的锁一定时间,然后再去获得锁,若超过了设置的超时时间就不需要使用notify方法唤醒,自动解除阻塞

3.核心线程满了之后什么时候开启线程,最大线程数满了又会怎么样?
空闲线程的存活时间,存活时间单位 ,最大线程数,核心线程数,任务队列,拒绝策略
当核心线程数满了的时候,同时任务队列也满了的话,此时就会创建新的线程,如果线程数达到最大线程数,此时就看设置的队列策略,若是丢弃最先进入的队列,再尝试放入新队列的

4.当前项目中token生成?
当前用户中心服务使用的是非对称加密的rs256算法实现的,通过jwt的各种方法实现token的生产,然后token的存储是根据业务是否需要支持,以某种形式存储到redis中的,目前设置的redis中的时间为2天,使用的是redis的惰性清除的策略,而验证码的存储设置的是访问key后清除value数据

5.网关对比

zuul:zuul网关是属于阻塞式api实现,只支持同步的
gateway:gateway是属于非阻塞式的,支持异步,同步相比于zuul,gateway自带负载均衡和限流的功能,但是也同时限制仅适合于Spring Cloud套件

6.lock锁和同步代码块的区别
lock是Lock类中的一个方法,synchronized只是java的关键字
lock中必须在finally中调用unlock方法释放锁,不然容易死锁。synchronized是线程执行完或者发生异常jvm自动释放锁
lock是公平锁,而synchronized是可公平,可判断的
lock方法实现的是大量同步,而synchronized是少量同步

7.过滤器和拦截器的区别
过滤器依赖servlet,拦截器不需要
过滤器基于函数回调,拦截去基于java的反射机制
过滤器可以对所有请求起作用,拦截器只对动态请求起作用
拦截器可以多次被调用(网关),过滤器只能在容器初始化时被调用一次

哈希槽一共16384个位置

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值