面试题ing
- 1.jdk1.8中的HashMap
- 2.JAVA各种集合的区别
- 3.SpringBoot和SpringMVC的区别
- 4.SpringMVC执行流程
- 5.重定向sendRedirect()和请求转发forward()的区别
- 6.会话技术Cookie和Session
- (7~10原创为微信公众号:我是程序汪)
- 7.spring bean生命周期
- 8.数据库乐观锁或悲观锁
- 9.Object常见方法
- 10.sleep和wait的区别
- 11.JAVA之四大作用域对象
- 12. Spring Cloud的面试题
- 13.Java多线程面试题整理及答案
- 14.JVM的三种回收方式
- 15.阿里面试题
- 16.数据库优化
- 17.spring依赖注入方式
- 18.sql优化
- 19.Mybatis中#{}和${value}的区别
- 20.Mybatis中除了select,insert,update,delete标签还有什么标签?
- 21.Mybatis的一级缓存和二级缓存
- 22.什么是线程池
- 23.Linux的常用命令
- 24.分布式事务
- 25.springboot的优缺点
- 26.如何判断这条sql语句是否可以优化
- 27.soa和微服务的区别
- 28.为什么使用dubbo
- 29.zookeeper和Eureka的区别
- 28.Tomcat
- 29.Mysql 隐式连接和显式连接的区别
- 30.final的用途
- 31.int和Integer的区别
- 32.volatile作用,可见性原理,与synchronized区别
- 33.Redis的五种类型和应用场景
- 34.Redis的淘汰策略
- 35.为啥Redis单线程模型也能效率这么高?
- 36.用了缓存之后会有啥不良的后果?
- 37.RDB和AOF都可以Redis的持久化
- 38.RDB和AOF到底该如何选择
- 39.完美的单例模式
- 40.类的加载过程(7个步骤)
- 41.线程池的核心参数
- 42.百万数据如何优化数据库
- 43.Docker
- 44.MySql删除重复数据只保留一条
- 45.值传递和引用传递
- 46.Spring的IOC和AOP
- 47.事务的四大特性和传播性质
- 48.Redis的基本特性和击穿雪崩
- 49.RabbitMQ的五种使用情况
- 50.SpringBoot的特点和常用注解
- 51.eureka和Dubbo的区别和两者特点和内部流程
- 区别(C、A、P含义分别是一致性、可用性、分区容错):
- 52.缓存的三大问题
1.jdk1.8中的HashMap
- hashmap类主要处理具有键值对特征的数据
- 非线程安全,具有较快的访问速度,遍历顺序不一致
- 允许空值和空键
- loadFactor:负载因子默认值0.75,threshold表示所能容纳的键值对的临界值,
threshold计算公式:数组长度*负载因子
size:实际键值对的数量
modCount:字段记录hashmap内部结构发生变化的次数
INITIAL_CAPACITY:hashmap的默认容量16 - 底层采用数组+链表+红黑树
- 数组部分称为哈希桶,链表长度大于或等于8时,链表数据将以红黑树存储,长度降到6以链表存储
- 每个node节点存储用来定位数据索引位置的hash值,key和value指向下一个节点的node<K,V> next节点组成
- 插入数据时,先调用hashcode()方法,获取key的hash值进行高位运算,得到数组下标
2.JAVA各种集合的区别
List Set Map
- list set都实现了collection接口是单列集合,list有序有索引可以重复 set无序无索引不可重复 map双列集合 key可以重复value不可以重复
List:
- Arraylist:底层数据结构:数组 查询快 增删慢 线程不安全 执行效率高 初始长度10 呈1.5倍扩容
- LinkedList: 底层数据结构:链表 查询慢增删快
- Vector:底层数据结构:数组 查询快 增删慢 线程安全效率低(一般不用)
Set:
HashSet:底层数据结构:哈希表 实际上是hashMap(new hashSet时底层会初始化一个hashMap),迭代无序;
LinkedHashSet:底层数据结构:哈希表+双向链表 继承于hashSet 底层是linkedHashMap (new linkedHashMap时底层会初始化一个LinkedHashMap)
TreeSet:底层数据结构:红黑树 实际上是TreeMap(new TreeSet时底层会初始化一个TreeMap),,TreeSet使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator进行排序
Map:
HashMap:底层数据结构:哈希表 哈希表底层数组+链表 线程不安全 效率高
LinkHashMap:继承与hashMap 底层哈希表+链表 链表的作用是保证有序
TreeMap:底层红黑树的数据结构 按 key 排序,默认的排序方式是升序。
HashTable:同hashMap相比 线程安全 效率低
数据结构
数据结构:
- 数组:查询快 增删慢
有索引的存在 可以根据索引快速定位 时间复杂度为o(1) 所以查询快
数组在内存中是连续的 长度不可变 每次增加删除 需要重新new一个出来 数据量越大效率越低 时间复杂度o(n) - 双向链表:查询慢 增删快
链表在内存中是分散的 是由很多节点组成 每个节点都有两个值 一个是具体存储的值 一个是指向下一个节点的地址值
增加 删除元素时 只需要改变指向下个节点的地址值即可 时间复杂度o(1)
查询元素时 只能从前向后找 直到找到为止 时间复杂度o(n) - 哈希表:数组+链表 主干是一条数组 数组的每个节点挂了很多链表
哈希表吸取了数组和链表各自的优点 使得增删改查速度都是非常快的 - 哈希冲撞:哈希表内部有一个哈希函数 哈希函数是用来计算元素存储的位置的 一个哈希函数的好坏 决定了一个hashMap 的性能
- 栈:先进先出
- 队列:先进后出
- 二叉树:每个节点最多有两个节点的数据结构
- 二叉查找数:在二叉树的基础之上增加了排序功能
- 平衡二叉查找树:最高子节点和最低子节点之间的高度差不超过1就是平衡的 红黑树是平衡二叉查找树其中的一种
3.SpringBoot和SpringMVC的区别
-
Spring 是一个“引擎”;
-
Spring MVC 是基于Spring的一个 MVC 框架;
-
Spring Boot 是基于Spring4的条件注册的一套快速开发整合包。
-
spring boot只是一个配置工具,整合工具,辅助工具.
springmvc是框架,项目中实际运行的代码
Spring MVC是基于Servlet 的一个 MVC 框架主要解决 WEB 开发的问题,因为 Spring 的配置非常复杂,各种XML、 JavaConfig、hin处理起来比较繁琐。于是为了简化开发者的使用,从而创造性地推出了Spring boot,约定优于配置,简化了spring的配置流程。
-
Spring MVC的功能
Spring MVC提供了一种轻度耦合的方式来开发web应用。
Spring MVC是Spring的一个模块,式一个web框架。通过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。解决的问题领域是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。
4.SpringMVC执行流程
5.重定向sendRedirect()和请求转发forward()的区别
- 重定向跳转:有两次请求;请求转发:有1次请求
- 重定向跳转:浏览器地址栏会变;请求转发:地址栏不变
- 重定向跳转:是客户端(浏览器)跳转;请求转发:是服务端跳转
详细讲解地址
6.会话技术Cookie和Session
- 用于临时保存会话过程中,产生的数据的技术,叫会话技术。
- 有两种会话技术:
- Cookie:把会话数据保存在了客户端,客户端的会话技术
- 优点:服务器压力小
- 缺点:不安全,只能保存字符串
- session:把会话数据保存在了服务端,服务端的会话技术。session依赖于Cookie
- 优点:安全性高,可以保存任意类型的数据
- 缺点:服务器压力大–集群解决
- Cookie:把会话数据保存在了客户端,客户端的会话技术
6.1判断是否应该使用会话技术
- 判断数据共享,是否需要区分会话。多个会话之间的数据,能否干扰。如果不能干扰,就要使用会话技术
- 判断数据的安全性要求,如果要求比较高,就使用session;如果安全性要求不高,就使用Cookie技术
6.2会话技术的经典使用场景
- 验证码的存储(session技术)
- 登录信息的保存(session技术,把登录的User对象放到session里)
- 购物车的数据保存(Cookie技术)
(7~10原创为微信公众号:我是程序汪)
7.spring bean生命周期
下面以BeanFactory为例,说明一个Bean的生命周期活动
- Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
- Setter注入,执行Bean的属性依赖注入
- BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
- BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
- BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法
- InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
- Bean定义文件中定义init-method
- BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法
- DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
- Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法
8.数据库乐观锁或悲观锁
- 乐观锁:一般利用表字段的version+1来实现(如SVN、GIT提交代码就是这样的)
- 悲观锁:一般是 where id=XX for update 来实现 (一般银行转账、工单审批)
乐观锁:性能高、重试失败成本不高建议乐观
悲观锁:性能低,但安全,失败成功高建议悲观,使用不当有死锁风险
9.Object常见方法
- toString、hashCode、equals 一定要知道吧
10.sleep和wait的区别
11.JAVA之四大作用域对象
12. Spring Cloud的面试题
13.Java多线程面试题整理及答案
13.1:线程池的执行流程(公众号:我是程序汪)
14.JVM的三种回收方式
15.阿里面试题
16.数据库优化
17.spring依赖注入方式
- 属性注入(类需要提供get、set方法)
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用property标签元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 value 子节点指属性值
属性注入是实际应用中最常用的注入方式 - 构造器注入
通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
构造器注入在 constructor-arg元素里声明属性, constructor-arg 中有 name 属性 - p标签注入(很少用)
18.sql优化
1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3、应尽量避免在 where 子句中使用!=或<>操作符,否则将导致引擎放弃使用索引而进行全表扫描。
4、应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
- union去重并排序,union all直接返回合并的结果,不去重也不排序;
- union all比union性能好;
5、in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6、下面的查询也将导致全表扫描:
select id from t where name like '%abc%'
7、应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
19.Mybatis中#{}和${value}的区别
#{}:表示一个占位符,相当于预编译对象的SQL中的?
- 可以有效防止SQL注入;
- Mybatis会自动进行参数的Java类型和JDBC类型转换;
- #{}中间可以是value或者其它名称
$ { value } :表示拼接SQL串,相当于把实际参数值,直接替换掉${value}
- 不能防止SQL注入
- Mybatis不进行参数的Java类型和JDBC类型转换
- 如果只有一个参数,并且是简单类型,${value}中只能是value,不能是其它名称
20.Mybatis中除了select,insert,update,delete标签还有什么标签?
- selectkey标签:在插入到表格之后或者之前,查询主键的值
- if标签:判断字符串(条件)相等与否
- if+where标签:一种代替where 1=1的技术:标签
21.Mybatis的一级缓存和二级缓存
(1)一级缓存(SqlSession级别)
MyBatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行
相同的sql语句,第一次执行后会将查询到的数据存储到缓存当中,第二次会从缓
存中进行查找,从而提高查询效率,当一个SqlSession结束之后,一级缓存也将不
存在,Mybatis默认开启一级缓存。当调用了SqlSession对象的修改、添加、删除、
commit()、close()、clearCache()等方法时,一级缓存会被清空。
(2)二级缓存(Mapper级别)
二级缓存的作用域是mapper的同一个namespace,执行两次相同的SQL语句,
第一次执行后会将查询到的数据存储到缓存当中,第二次会从缓存中进行查找,从而提高查询效率,默认不开启。
由同一个SqlSessionFactory对象生产的SqlSession对象,同样的映射器Mapper共享其缓存。
22.什么是线程池
- 其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
线程池面试题合集
23.Linux的常用命令
- mkdir 目录名 :创建目录
- cd 目录名:切换到指定目录
- touch 文件名:创建文件
- vi 文件名:编辑文件
- :wq :保存退出
- rm 文件名:删除文件
- mv 文件名 目录名:移动文件到指定目录
- cp 源文件 新文件:拷贝
- tar -zcvf 压缩包 文件1 文件2 …
- tar -xvf 压缩包 -C 解压位置 :解压缩文件
命令合集
24.分布式事务
25.springboot的优缺点
- 优点:
- 去除了大量的xml配置文件
- 简化复杂的依赖管理
- 配合各种starter使用,基本上可以做到自动化配置
- 快速启动容器
- 配合Maven或Gradle等构件工具打成Jar包后,Java -jar 进行部署运行还是蛮简单的
- 创建独立Spring应用程序,嵌入式Tomcat,Jetty容器,无需部署WAR包,简化Maven及Gradle配置,尽可能的自动化配置Spring,直接植入产品环境下的实用功能,比如度量指标、健康检查及扩展配置等,无需代码生成及XML配置。
- 缺点:
- 集成度较高,使用过程中不太容易了解底层
- 因为不要自己做配置,项目有的时候会报错,不容易解决
26.如何判断这条sql语句是否可以优化
- 使用explain关键字可以模拟优化器执行Sql出现语句,从而知道Mysql是如何处理你的sql语句的。分析你的查询语句或是表结构的性能瓶颈
27.soa和微服务的区别
-
集成方式不同:
SOA倾向于去中心化的集成方式
-
运行方式不同:
每个微服务都可以单独运行在自己的进程中,互补影响 SOA依托于企业服务总线ESB 因为SOA的核心是ESB,又因为ESB内部包含通信协议的解析,数据的序列化和反序列化, 业务流程的编排和服务路由等,因此很笨重 微服务采用的是轻量级的通信协议,一般是HTTP,数据格式也比较简单
-
服务粒度不同:
由于ESB很重,所以SOA在做系统拆分时粒度只能大 而微服务没这个顾虑,因此它的粒度可以拆的很小;
28.为什么使用dubbo
优点:
1.远程通讯: 提供对多种基于长连接的NIO框架抽象封装, 包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
2.软负载均衡及容错机制: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3.服务自动注册与发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器 。
4.提供完善的管理控制台dubbo-admin与简单的控制中心dubbo-monitor
5.Dubbo提供了伸缩性很好的插件模型,很方便进行扩展(ExtensionLoader)
6.支持多协议
7.Dubbo采用全spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配
29.zookeeper和Eureka的区别
- 分布式中著名的CPA理论:一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。
- Zookeeper:
集群节点为主从关系,注册以主节点为主,在一个设备上完成,这样可以提高分区容错性,同时具备数据一致性。主节点以复制的方式将数据同步到从节点,当同步数据量大时,服务不可用,性能降低,所有放弃了服务可用性。 - Eureka:
集群节点间发送心跳包,如果某个节点发送心跳包而其他节点没有收到,Eureka会将该节点做服务保护,从而提高分区容错性。集群节点是平等的,服务可以从任何一个节点提供,所以具备服务可用性,而放弃了数据一致性(这里并不是完全放弃数据一致性,而是放弃数据的强一致性,保留数据的最终一致性。举个栗子:淘宝购物服务如果同时接受两个订单,那么较晚的订单将被告知售罄。)。
28.Tomcat
29.Mysql 隐式连接和显式连接的区别
语法区别:
- 隐式连接:SELECT * FROM test_1,test_2 WHERE test_1.id = test_2.id;
- 显示连接: SELECT * FROM test_1 JOIN test_2 ON (class_no = course_no);
性能区别:隐式连接快于显示连接
30.final的用途
1、修饰类,不能被继承
2、修饰常量,初始化赋值,不能修改
3、修饰方法,不能被覆盖
31.int和Integer的区别
- int是基本数据类型,Integer是int的包装类;int的初始值为0,Integer的初始值为null
32.volatile作用,可见性原理,与synchronized区别
volatile 关键字的作用
保证内存的可见性
防止指令重排
注意:volatile 并不保证原子性
可见性原理
volatile 保证可见性的原理是在每次访问变量时都会进行一次刷新,因此每次访问都是主内存中最新的版本。所以 volatile 关键字的作用之一就是保证变量修改的实时可见性。
volatile 和 synchronized区别
1、 volatile 轻量级,只能修饰变量。synchronized重量级,还可修饰方法
2、volatile 只能保证数据的可见性,不能用来同步,因为多个线程并发访问 volatile 修饰的变量不会 阻塞。
synchronized 不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢 synchronized 锁对象时,会出现阻塞。
3、volatile 并不能保证线程安全性。而 synchronized 则可实现线程的安全性
33.Redis的五种类型和应用场景
string——适合最简单的k-v存储,类似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。
hash——一般key为ID或者唯一标示,value对应的就是详情了。如商品详情,个人信息详情,新闻详情等。
list——因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。
set——无序集合,自动去重,可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set最牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人共同的好友等。
Sorted Set——是set的增强版本,增加了一个score参数,自动会根据score的值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据。
例子:排行榜:将每个用户以及其对应的什么分数写入进去,zadd board score username,接着zrevrange board 0 99,就可以获取排名前100的用户;zrank board username,可以看到用户在排行榜里的排名
34.Redis的淘汰策略
- 定期删除
- 假设存了一定数量的key并且设置了过期时间(如果存过多key,可能cpu消耗在了检查过期key上,redis就死了),redis默认每隔100ms进行抽取一下设置了过期时间的key,判断是否过期,如果过期则删除。但是问题是,定期删除可能会导致很多过期key到了时间并没有被删除掉。这时候惰性删除的作用来了。
- 惰性删除
- 当你在获取某个key的时候,redis会检查这个key的是否有过期时间,并且判断是否过期,如果过期则不会返回任何东西。但是,如果定期删除遗留的key没有被我们访问的时候,还是会漏掉许多过期key,这时候走内存淘汰机制
- 内存淘汰
- 如果redis的内存占用过多的时候,此时会进行内存淘汰,有如下一些策略
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的key给干掉啊
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
- 如果redis的内存占用过多的时候,此时会进行内存淘汰,有如下一些策略
35.为啥Redis单线程模型也能效率这么高?
- 纯内存操作
- 核心是基于非阻塞的IO多路复用机制
- 单线程反而避免了多线程的频繁上下文切换问题(百度)
36.用了缓存之后会有啥不良的后果?
- 缓存与数据库双写不一致
- 缓存雪崩
- 缓存穿透
- 缓存并发竞争
37.RDB和AOF都可以Redis的持久化
-
两者有一定的区别:
- Redis默认是开启RDB的,AOF默认关闭,需要手动开启;
- RDB和AOF同时开启的情况下,会只加载AOF
- RDB持久化机制,对redis中的数据执行周期性的持久化
- AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集
- 同时使用RDB和AOF两种持久化机制,那么在redis重启的时候,会使用AOF来重新构建数据,因为AOF中的数据更加完整
-
RDB持久化机制的优点
- RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,可以将这种完整的数据文件发送到一些远程的安全存储(云服务)上去
- RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可
- 相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速
-
RDB持久化机制的缺点
- 如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好。一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据
- RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒
-
AOF持久化机制的优点
- AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据
- AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复
- AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
- AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复
-
AOF持久化机制的缺点
- 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
- AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
38.RDB和AOF到底该如何选择
- 综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择; 用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复
39.完美的单例模式
// Effective Java 第一版推荐写法
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
这种写法非常巧妙:
-
对于内部类SingletonHolder,它是一个饿汉式的单例实现,在SingletonHolder初始化的时候会由ClassLoader来保证同步,使INSTANCE是一个真·单例。
-
同时,由于SingletonHolder是一个内部类,只在外部类的Singleton的getInstance()中被使用,所以它被加载的时机也就是在getInstance()方法第一次被调用的时候。
-
它利用了ClassLoader来保证了同步,同时又能让开发者控制类加载的时机。从内部看是一个饿汉式的单例,但是从外部看来,又的确是懒汉式的实现。简直是神乎其技。
40.类的加载过程(7个步骤)
- 加载:
- 类的全限定类名获取类的二进制流
- 将二进制流中的静态存储结构化为方法区域的运行时数据结构
- 在JAVA堆中生成这个类的class对象作为入口
- 验证:确保Class文件不会对JVM造成危害
- 文件格式验证
- 元数据验证
- 字节码验证
- 符号引用验证
- 准备:为变量分配内存空间,并设置变量的初始化
- 解析
- 初始化
- 使用
- 卸载(第6步和第7步使用过程就是根据程序定义的行为执行,卸载由GC完成)
41.线程池的核心参数
- corePoolSize:核心线程数,线程池启动时就会创建的线程数量
- maximumPoolSize:最大线程数,线程池中最大的线程数量
- keepAliveTime:线程超时时间,看源码可知,该参数的意义是线程从工作队列中取出任务的超时时间
42.百万数据如何优化数据库
43.Docker
- 什么是容器?
依托与Linux内核的虚拟化技术 - 什么是Docker?
把应用程序自动部署到容器的开源引擎
Docker容器介绍
44.MySql删除重复数据只保留一条
实例:
数据库表:
- 执行sql语句查询重复字段
select name from test group by name having count(*)>1
- 删除重复数据保留一条最大id的数据
sql语句:
delete from test
where name in (select t.name from (select name from test group by name having count(*)>1) t)
and id not in (select t.id from (select max(id) id from test group by name having count(*)>1) t)
45.值传递和引用传递
- 结语
因此可见:在Java中所有的参数传递,不管基本类型还是引用类型,都是值传递,或者说是副本传递。
只是在传递过程中:
如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值,并且是在不同的栈区,因此形参的操作,不影响原始内容。
如果是对引用类型的数据进行操作,分两种情况,
一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。
一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。
46.Spring的IOC和AOP
47.事务的四大特性和传播性质
48.Redis的基本特性和击穿雪崩
基本特性
string——适合最简单的k-v存储,类似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。
hash——一般key为ID或者唯一标示,value对应的就是详情了。如商品详情,个人信息详情,新闻详情等。
list——因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。
set——无序集合,自动去重,可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set最牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人共同的好友等。
Sorted Set——是set的增强版本,增加了一个score参数,自动会根据score的值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据。
例子:排行榜:将每个用户以及其对应的什么分数写入进去,zadd board score username,接着zrevrange board 0 99,就可以获取排名前100的用户;zrank board username,可以看到用户在排行榜里的排名
防止雪崩解决方案
49.RabbitMQ的五种使用情况
50.SpringBoot的特点和常用注解
优点:
3.1、快速构建项目。
3.2、对主流开发框架的无配置集成。
3.3、项目可独立运行,无须外部依赖Servlet容器。
3.4、提供运行时的应用监控。
3.5、极大的提高了开发、部署效率。
3.6、与云计算的天然集成。
常用注解:
(1)@RestController和@Controller指定一个类,作为控制器的注解 ,并说明其区别
(2)@RequestMapping方法级别的映射注解,这一个用过Spring MVC的小伙伴相信都很熟悉
(3)@EnableAutoConfiguration和@SpringBootApplication是类级别的注解,根据maven依赖的jar来自动猜测完成正确的spring的对应配置,只要引入了spring-boot-starter-web的依赖,默认会自动配置Spring MVC和tomcat容器
(4)@Configuration类级别的注解,一般这个注解,我们用来标识main方法所在的类,完成元数据bean的初始化。
(5)@ComponentScan类级别的注解,自动扫描加载所有的Spring组件包括Bean注入,一般用在main方法所在的类上
(6)@ImportResource类级别注解,当我们必须使用一个xml的配置时,使用@ImportResource和@Configuration来标识这个文件资源的类。
(7)@Autowired注解,一般结合@ComponentScan注解,来自动注入一个Service或Dao级别的Bean
(8)@Component类级别注解,用来标识一个组件,比如我自定了一个filter,则需要此注解标识之后,Spring Boot才会正确识别。
51.eureka和Dubbo的区别和两者特点和内部流程
区别(C、A、P含义分别是一致性、可用性、分区容错):
Zookeeper保证CP(一致性和容错性)
zookeeper服务注册功能对可用性的要求要高于一致性。zk当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
Eureka保证AP(可用性和容错性)
Eureka在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。
Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
-
Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
-
Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
-
当网络稳定时,当前实例新的注册信息会被同步到其它节点中
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
工作原理:一、eureka的工作原理
eureka包含两个组件,eureka serve 和eureka client,eureka client是一个Java程序客户端,用于简化和eureka serve的交互。
Eureka Server提供服务发现的能力,各个微服务启动时,会通过Eureka Client向Eureka Server进行注册自己的信息(例如网络信息),Eureka Server会存储该服务的信息;
微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒)以续约自己的信息。如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒);
每个Eureka Server同时也是Eureka Client(),多个Eureka Server之间通过复制的方式完成服务注册表的同步;
Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者。
52.缓存的三大问题
1.缓存穿透:缓存没有,数据库也没有
解决方案:1.缓存放空对象2.使用布隆过滤器(优点:占用空间小,但是无法删除)介绍和原理
2.缓存击穿:缓存没有,数据库有(并发问题)
解决方案:使用分布式锁解决
3.雪崩
解决方案:集群