Java面试

Java基础

hashmap:

底层是数组+链表+红黑树的结构;
默认容量16 设置默认容量可以提高效率
线程不安全
key只能一个null,value可以多个null

HashMap在put方法中,它使用hashCode()和equals()方法。当我们通过传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。如果索引处为空,则直接插入到对应的数组中,否则,判断是否是红黑树,若是,则红黑树插入,否则遍历链表,若长度不小于8,则将链表转为红黑树,转成功之后 再插入。

红黑树的特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
新插入数据会破坏他的平衡,会进行左旋或者右旋

concurrenthashmap

结构:数组+红黑树+链表
cas+synchronized 保证线程安全
区别:hashtable是阻塞的
concurrenthashmap 是非阻塞的
CAS:Compare and Swap,即比较再交换。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
对CAS的理解,CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

TreeMap LinkedHashMap

TreeMap和LinkedHashMap是有序的(TreeMap默认升序,LinkedHashMap则记录了插入顺序)。

arrayList与linkedList

arrayList是数组结构,linkedList是链表结构 arrayList查询快,增删慢,linkedList增删快查询慢,原因是因为linkedList每一个节点会储存两个引用,一个志向上个节点,一个指向下个节点,而arrayList需要重新计算大小或者更新索引,也因此linkedList更占内存

String StringBuffer StringBulider

String 生成的字符串在常量池
StringBuffer 线程安全
StringBuilder 线程不安全
最好使用后两者,使用append方法只创建一个对象

Java反射

反射机制是指你已知一个类的所有方法与字段时,可以获取使用类中的方法与字段

调用反射的三种方法
.class getclass class.forname()

io nio aio

bio 同步阻塞io
nio 同步非阻塞io channel,buffer,selector
channel将数据读或者写入buffer,selector监控channel,如果有一个或多个通道发生变化就进行读写 多路复用io
aio 异步非阻塞io,用户线程发起read请求,直接返回,当内核数据准备完毕,返回成功信息,即可直接使用数据

selector 与epoll

selector内部维持了一个数据结构(bitmap),用来存储已经接受的socket对象。然后将此数据复制一份,交给内核去轮训每个socket对象是否有期待的事件发生,如果有就会进行置位(用户态到内核态的复制)。然后返回给用户态,由用户态完成事件的处理。
epoll针对selector进行了优化,采用红黑树来存储accept的socket对象,同时还维持着一个list,存放有发生的事件的socket以及事件,然后将此任务队列返回。用户态无需遍历所有的socket对象。

动态代理

JDK的动态代理底层是反射,依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了
cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

cookie session

cookie是存放在客户端的,session是存放在服务器的
cookie支持跨域,session不支持跨域
cookie放在客户端对用户是可见的,session是不可见的,比较安全
cookie是实现session的一种方式

jdk 1.8新特性

1.lambda表达式
2.Stream APi groupingby
3.新日期类型 localdatetime

tcp三次握手

第一次:客户端向服务端发起请求,发送syn(seq=j)包
第二次:服务器接收到syn包,同时自己也发送一个syn包给客户端,等于发送了一个ack+syn
第三次:客户端接收到服务器的syn包与ack包,向服务器发送一个ack包,发送完毕之后,进入链接

其中ACK报文是用来应答的,SYN报文是用来同步的

四次挥手

(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端。
(4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

http 和https的区别,以及https是如何保证安全的;

答: 1.http是明文传输,https是加密传输
2.https加了一层ssl/tls协议
3.https需要使用ca证书,且收费;
https加密过程:1.服务器将公钥给浏览器 -->2.浏览器拿到公钥之后,生成一个“会话密钥"--->3.用公钥加密这个“会话密钥”发送给服务器--->4.数据传输的过程中,就用这个会话密钥来加密数据

引用类型

1.强引用:直接new ,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。
2.软引用:SoftReference ,只有在内存不足的时候JVM才会回收该对象,适合用来做缓存
3.弱引用:WeakReference,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象
4.虚引用:RefrenceQueue,如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收

多线程

创建线程的三种方法

继承thread
实现runable
重写run方法

四种线程池

newcachedThreadpool:如果线程不够用就新建,如果60秒线程还没使用就销毁
newfixedthreadpool:固定线程数,不够用就排队
newschedulethreadpool:定时任务
newsinglethreadexecutor:单个线程的线程池

线程池常用的参数

1.corePoolSize:核心线程数
核心线程会一直存活,即使没有任务需要执行。
当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理。
设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭。
2.queueCapacity:任务队列容量(阻塞队列)
当核心线程数达到最大时,新任务会放在队列中排队等待执行。
3.maxPoolSize:最大线程数
当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务。
当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常。
4.keepAliveTime:线程空闲时间
当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize。
如果allowCoreThreadTimeout=true,则会直到线程数量=0。

线程的生命周期

新建:new
就绪:start
运行:run
阻塞:sleep wait
死亡:运行结束或报错或调用stop方法

sleep 与wait

sleep方法是thread的,wait是object的
sleep不会释放对象,只是让出了CPU,等到一定的时间,会自动恢复运行状态
wait会释放对象,需要notify唤醒

多线程按顺序执行

countdownlatch

volatile

volatile 适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。
volatile 是直接从主内存拿的数据

框架

Spring IOC

通过Java的反射原理,将bean交由spring管理

spring aop

面向切面编程,底层是动态代理
简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP 把软件系统分为两个部分:核心关注点和横切关注点。
用于日志,事务,权限认证等

springcloud

springcloud 是一系列框架的有序集合,包括了注册中心,服务网关,负载均衡等组件,利用了springboot的开发便利,实现了一键启动和部署

Spring Cloud 解决了哪些问题

1.与分布式系统相关的复杂性 – 包括网络问题,延迟开销,带宽问题,安全问题。
2.处理服务发现的能力 – 服务发现允许集群中的进程和服务找到彼此并进行通信。
3.解决冗余问题 – 冗余问题经常发生在分布式系统中。
4.负载均衡 – 改进跨多个计算资源(例如计算机集群,网络链接,中央处理单元)的工作负载分布。
5.减少性能问题 – 减少因各种操作开销导致的性能问题。

负载均衡的算法

1.轮询法
不管服务器的连接数,均衡的对待每一台机器
2.随机法
系统的随机算法,随便访问一台机器
3.源地址哈希法
对请求的用户的IP地址进行哈希计算,得到一个数值,再对这个数值进行取模运算,得到的结果就是访问的服务器的编号,这样有一个好处,同一个用户访问的都是同一台服务器
4.加权轮询法
5.加权随机法
6.最小连接数法
不同的服务器,配置不同,处理请求的速度有快慢,这个时候可以根据服务当前的连接数,选择连接数最少的一台进行请求

核心组件

eureka:注册中心,注册与发现
ribbon:实现负载均衡
Feign:根据URL调用服务,整合了ribbon与hystrix
hystrix:提供线程池,不同服务走不同线程池,实现服务隔离
zuul:网关,由zuul转发请求给对应的服务

springcloud 与dubbo

Springcloud是Apache给出的微服务治理方案,有一整套自己的组件
dubbo是阿里给出的分布式方案,依赖zookeeper
dubbo使用RPC调用,springcloud是rest API
注册中心来看springcloud有自己的注册中心eureka,也可以整合zookeeper
dubbo使用zookeeper

springboot 与 springcloud

1.springboot专注于单个微服务的搭建
2.springcloud专注于各个微服务之间的治理整合管理,未各个微服务提供网关配置路由等
3.springcloud依赖springboot,springboot不依赖springcloud

微服务之间是如何通讯的

1.远程调用
我们说的RPC调用已经rest api
需要一个注册中心,把我们的微服务注册上去
2.消息中间件
mq

Springcloud Bus

bus 是将分布式的节点用轻量的消息连接起来,可以用于监控,也可以用于spring配置文件更改或服务之间的通讯使用

eureka 与 zookeeper

zookeeper 当机了会重新选举leader,虽然最终会恢复,但是选举期间是不可用的
eureka 是平等的,当前有一台当机了不会影响使用,新服务也可以注册上来,但是不会同步到其他节点去,等服务恢复了,才会同步,最终一致性

BeanFactory 与 FactoryBean

BeanFactory是个bean 工厂,是一个工厂类(接口), 它负责生产和管理bean的一个工厂
是ioc 容器最底层的接口,是个ioc容器,是spring用来管理和装配普通bean的ioc容器(这些bean成为普通bean)。
FactoryBean是个bean,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂bean,由spring管理后,生产的对象是由getObject()方法决定的(从容器中获取到的对象不是“ FactoryBeanTest ” 对象)。

feign实现原理

使用@enablefeignclient 开启feignclient
对实现的接口使用@feignclient
服务启动的时候,会把带有feignclient的接口放入IOC容器中
当调用的时候,会通过代理,来生成具体的requesttemplate
requesttemplate生成request
request调用client,例如HTTPclient
最后client被封装到loadbanlanceclient类,这个类结合了ribbon做了负载均衡

springboot初始化

1.调用mian的run方法主要做了以下三件事
判断是否需要启动一个webapplicationcontext
springfactoriesinstances加载classpath下所有可用的applicationContentInitializer
springfactoriesInstances加载classpath下所有可用的applicationListener

JVM

JVM的主要部分

1、类加载器
2、运行时数据区
3、执行引擎
4、本地库接口
首先要通过类加载器对Java文件编译成字节码文件,然后由运行时数据区读取到内存中,由执行引擎将字节码翻译成特定的底层系统指令再交由CPU去执行,这个过程需要调用本地库接口实现;

运行时数据区

堆:是虚拟机中占用内存最大的一块,几乎所有的对象都会在这里
栈:储存局部变量表,操作数栈,方法出口等
方法区:储存类加载信息,常量,静态变量等
程序计数器:当前线程所执行的行号指示器,字节码解析工具时就是改变当前程序计数器,用来获取下一个指令
本地方法栈:与栈作用一样,只是调用的native方法

堆是可共享的区域
分为年轻代,老年代,永久代(1.8之后叫元数据区)
年轻代又分为Eden跟from survivor,to survivor比例是8:1:1
是gc主要区域

gc过程

对象在Eden出生,当Eden内存满了之后,进行第一次gc,将存活下来的对象复制到from survivor中,Eden中的所有对象都回收掉,当Eden再次满了之后,就会进行再次gc,将Eden与from survivor 中存活的对象放到to survivor 中,将Eden于from中的对象都回收掉,如此反复大概15次的样子,还存活着的对象会进入老年代;

存的都是栈帧,包括局部变量表,操作数栈,方法出口等,生命周期是随着方法的调用而创建,随着结束而销毁

双亲委派模型

双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。

怎么看一个对象是否可以回收

1.引用计数法: 为每创建的一个对象做一个引用计数,如果被引用就+1,没有被引用就是0,那么计数为0的就是可回收对象;
2.可达性分析:从gc roots开始向下搜索,搜索走过的路径称为引用链,当对象与gc roots没有引用链时,称为不可达对象,可以回收

gc roots 对象

虚拟机栈(栈桢中的本地变量表)中的引用的对象 ;
方法区中的类静态属性引用的对象 ;
方法区中的常量引用的对象 ;
本地方法栈中JNI的引用的对象;

类加载的5个过程

加载,检查,准备,解析,初始化

垃圾回收算法

复制算法(新生代)
标记-清除算法(老年代)
分代算法
标记-整理算法

jvm 的垃圾回收器

CMS:以最小停顿为目标的回收器,以牺牲吞吐量为代价,标记清除算法,老年代
G1:一种兼顾吞吐量和停顿时间的收集器,标记整理算法,分代垃圾回收

cms回收过程

1.初始标记,会造成stw
2.并发标记,可以与用户线程一起处理
3.预清理
4.可被终止的预清理
5.重新标记,会造成stw
6.并发清除
7.并发重置状态下等待cms的触发

什么情况下会引发full gc

1.调用system.gc,可配置参数不调
2.堆中分配了非常大的对象
3.老年代内存不足
4.永久代内存不足

Redis

Redis 使用场景

数据高并发的读写
海量数据写入

Redis的作用

做缓存
分布式锁

Redis数据格式

String,list,set,zset,hash

Redis怎么实现分布式锁

setnx

缓存穿透,缓存击穿,缓存雪崩

缓存击穿是数据库与缓存中都没有的数据
解决方法:1.添加用户校验信息 2.获取不到数据的情况下缓存一份到数据库,时间短一点例如30秒

缓存击穿是指数据库中有但是缓存中没有的,很多用户同时获取去访问数据库
1.设置热点永不过期
2.互斥锁

缓存雪崩是指大批量的数据同时失效,都去查数据库了,造成数据库当机
1.缓存过期时间随机,不要同时失效
2.热点数据设置永不过期
3.缓存降级

MySQL

数据库的三范式

第一范式:列的原子性,每一列(字段)都是不可分割的,例如省市区
第二范式:属性完全依赖主键,例如学生与成绩表
第三范式:属性不依赖于其他非主属性,只依赖于主属性

数据库事务

原子性:同一事务下所有操作,都是要么一起成功,要么一起失败
一致性:几个一起执行的事务,其执行结果必须按某一顺序执行的结果一致
隔离性:事务不接受其他事务的干扰
永久性:已经提交的事务,对数据库的影响必须是永久的

主从复制

主库binlog写入,从库读取并写入relaylog 执行relaylog

myisam 与 innodb

myisam不支持事务,innodb支持事务
myisam支持表级锁,innodb支持行级锁
myisam支持全文检索,innodb不支持
如果读操作超过写操作可以使用myisam

char ,vachar

char是固定长度vachar是可变长度,char固定长度10,varchar(50)中50的涵义最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存

数据库优化

1.使用索引,建表的时候合理字段
2.SQL优化,少使用left join,null,like,not等
3.尽量使用临时表,比如我查询统计结果
4.如果数据量非常大,我们就要考虑分库分表的操作了

mvcc

数据库版本并发控制
利用已提交读跟可重复读生成的readVIew不同,实现了读写-写读的并发执行,提升了系统的性能

索引

主键索引,唯一索引,普通索引
组合索引(最左匹配原则)

Explain

Explain是Mysql的自带查询优化器,负责select语句的优化器模块,可以模拟优化器执行SQL查询语句,从而知道Mysql是如何处理SQL的,语法也很简单:Explain + SQL
用途:
(1)表的读取顺序,id
(2)数据读取操作的操作类型,select_type
(3)哪些索引可以使用
(4)哪些索引被实际使用
(5)表之间的引用
(6)每张表有多少行被优化器查询 rows

创建索引的原则

更新频繁的列不应设置索引
数据量小的表不要使用索引(毕竟总共2页的文档,还要目录吗?)
重复数据多的字段不应设为索引(比如性别,只有男和女,一般来说:重复的数据超过百分之15就不该建索引)
首先应该考虑对where 和 order by 涉及的列上建立索引

mysql事务的隔离级别

读未提交,读已提交,可重复读,序列化,MySQL是可重复读

rabbit mq

使用场景

1.跨系统的异步通信;例如我们项目中用到的新用户注册成功后会发送一条短信和一条站内信,这时候我们就可以使用mq

rabbit mq 的好处

1.解耦
2.异步
3.削峰

rabbit mq 组件

channel
publish
consumer
queen
exchange

丢消息了怎么办

消息持久化:消息队列丢消息
ack确认机制:confirm指派唯一ID,如果没有确认生产者将会重新发放消息
补偿机制:消费者丢消息了,例如aop重试机制

算法

lru 算法

1.lru
最近最少使用算法,算法根据历史访问记录来进行淘汰数据,核心思想就是说你最近访问过数据,那么将来呗访问的几率也很高;
最简单的实现方法.继承linkedhashmap,构造方法传入true,重写removeEldestEntry方法,制定删除策略
最常见的实现是利用链表保存数据,新加入的数据在表头,每当数据命中缓存,将数据迁移到表头,当链表满的时候,将表尾的数据删除
【命中率】
当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。
【复杂度】
实现简单。
【代价】
命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。
2.lru-k
lru-k需要多维护一个队列,队列维护一个访问次数,假设访问次数为k次,只有访问到达一定次数了,才会将缓存移到lru表头,剩下的维护顺序与lru一致
3.URL-Two queues
也是两个队列,不同的2q是FIFO缓存队列,即加上lru一共维护了两个缓存队列,且不用计算访问次数,第二次访问就将FIFO缓存数据放到lru中,其余删除新增一样
4.Multi Queue
优先访问缓存次数最多的,这边要维护多个队列

冒泡排序算法

冒泡排序算法也称为下沉排序。在这种类型的排序中,要排序的列表的相邻元素之间互相比较。如果它们按顺序排列错误,将交换值并以正确的顺序排列,直到最终结果“浮”出水面。

二分查找

也称折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置
的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,
则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。

插入排序算法

构建有序序列,对未加入序列的数据,对已排序的序列从前往后查找,找到相应的位置并插入

设计模式

单例模式:恶汉和懒汉模式,runtime用单例
工厂模式
装饰者模式:io
策略模式
观察模式
代理模式
建造者模式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350