2019春招面试问题及日常java技术总结

2019春招面试技术及日常java技术总结

总结不易,转载请注明出处 https://blog.csdn.net/zhangjingao/article/details/90903667

过了2019春招后,总结下自己在春招面试题和面试过程中遇到的问题,分各个类别进行了总结,在此分享,有不对的地方欢迎留言指出

软件工程

增量模型:把待开发的软件系统模块化,将每个模块作为一个增量组件,从而分批次地分析、设计、编码和测试这些增量组件

白盒与黑盒测试

白盒测试关注与内部代码设计,测试依据是设计文档。

黑盒测试关注的是输入与输出,依据的是需求文档。

多线程

死锁产生条件:互斥,占有并等待,非抢占(资源不能被抢占),循环等待

阻碍形成四个条件为死锁预防,死锁避免为动态的检测分配的资源是否安全

上下文切换:多线程会共同使用计算机上的cpu,当线程数大于系统分配给程序的cpu数时,cpu就会在各个线程之间轮转运行,不同的线程之间切换cpu发生的切换数据就是上下文切换。

Lock和Synchronized区别:

1、 Lock支持非公平锁和公平锁;

2、 可以让线程在等待锁的时候响应中断;

3、 可以让线程尝试获得锁,并在无法获得锁的时候立即返回或者等待一段时间;

4、 可以在不同的范围,以不同的顺序获得和释放锁。

特殊关键字

yield

使cpu暂停执行该线程,并将cpu交给其他线程执行,也可以执行自己,具体执行谁由cpu决定

join

该线程等待调用join方法的线程执行完后才继续执行

wait

使该线程等待(时间可设置),一般结合notify使用

notify、notifyAll

notify唤醒等待的线程,notify唤醒全部等待的线程

阻塞队列

阻塞队列额外支持两个操作(类比生产者消费者):1、在队列满时添加线程会等待队列可用;2、在队列空时获取线程会等待队列非空。举例:ArrayBlockingQueue

不可变对象

一旦创建状态就不会在发生变化的对象。如:string,基本类型的包装类,BigInteger等。

不可变对象永远都是线程安全的。

线程调度算法:

1、 分时调度算法(时间片轮转)

2、 抢占式调度算法(优先级调度,如果优先级相同,随机调度)

创建线程的方式

1、 实现Thread类;

2、 继承Runnable接口;

3、 实现Callable接口,实现call方法。

为什么会指令重排

为了提高性能,处理器和编译器会对执行的指令进行指令重排。指令重排有俩条件:

1、 单线程下不影响最终结果

2、 不存在数据依赖关系

线程池(executor)

为什么使用Executor框架/h4>

1、创建线程比较耗费资源;

2、使用new thread实现的new线程不方便管理;

3、使用new thread创建的线程不利于扩展。

有5个基本参数,两个可选参数

1、 corePoolSize:核心线程数:核心线程数,不会回收的数量

2、 maximumPoolSize:最大线程数:线程池允许创建的最大线程数

3、 keepAliveTime:保持空闲的时间:如果当前没有任务,线程池不会直接回收线程,而是当线程在空闲时间内仍然没有任务才会回收。

4、 timeUnit:**保持空闲时间的时间单位:**空闲的时间单位

5、 BlockQueue:**阻塞队列:新任务来时当线程数量大于corePoolSize,就会被封装成worker会先被放入阻塞队列,等待空闲线程执行,阻塞队列有很多种:ArrayBlockingQueue(有界队列),建议将队列的长度设置为maxiMumPoolSize,这样可以充分利用线程池。还有LinkedBlockingQueue(无边界队列)**设置了它后maxiMumPoolSize就不起作用了,因为队列永远不会满。

6、 threadFactory:**创建线程的线程池:**默认Executors.defaultThreadFactory(),使创建的线程具有相同的优先级。

7、 handler:线程池的饱和策略:如果队列满了并且线程池大小达到了最大,那么就会执行饱和策略,默认AbortPolicy,直接抛出异常,CallerRunsPolicy:用调用者所在的线程来执行任务,DiscardOldestPolicy:丢弃阻塞队列中靠前的任务,并且执行当前任务,DiscardPolicy:直接丢弃

各参数意义:

执行策略

当有新的任务到来时:

1、 当前线程数小于corePoolSize时不管是否有空闲线程,都会新建线程去执行。

2、 当前线程数大于corePoolSize但是小于MaxiMumPoolSize时,当阻塞队列满的时候才回去创建新的线程。

3、 当线程数等于最大线程并且队列满了,那么就会执行饱和策略(如果使用的是LinkedBlockingQueue,队列永远不会满,maxiMumPoolSize就没有任何作用了)。

数据结构

二叉树:

确定一个二叉树的遍历方式:先序和中序或者中序和后序。

叶子结点数=出度为2的节点数+1

二分查找树

是一个按大小排好序的树,左子树比结点小,右子树比节点大;

查找:跟结点值比较,大则往左查,小则往右查;

添加:同样查找比较后为null则插入,有值则覆盖;

删除

1.将值置为null,在树中保留键;

2.删除最小值:一直向左找到左子树为null的节点,用它的右子节点代替它。

3.Hibbard deletion

2-3树

二叉查找树的变形,有两种结点。

2-node:一个键,两个分叉

3-node:两个键,三个分叉

如果在3-node中插入一个值,使其变成了4-node,那么就此时它会有三个键,将中间的键移到父节点,直到根节点,如果根节点也变成了4-node,那么就将其变成3个2-node(中间的值变成新的2-node根节点,各连接之前根节点的左右值——高度+1仅可能由根节点分裂导致)

在查找和插入中,保证了logarithmic的性能。

最坏情况下:lgN,所有的结点都是2-node

最好情况下:log3N,所有的结点都是3-node

红黑树

红黑树是一种自平衡二叉查找树(通过变色和旋转)

1、 节点是红色或黑色;

2、 根节点是黑色;

3、 每个叶子节点都是黑色的空节点(NIL节点);

4、 每个红节点的两个子节点都是黑节点;

5、 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

红黑树的应用:java中的TreeMap,TreeSet,jdk1.8的HashMap

插入和删除需要O(logn)的时间和空间

B树(B-树)

B树是一个平衡多路查找树

1、 结点关键字满足查找树规则;

2、 子节点数:非叶子节点的子节点数>1,且<=M,M>=2(空树除外),M代表查找路径,也就是路数;

3、 枝节点的关键字数量>=ceil(m/2)-1,且小于等于m-1个;

4、 所有叶子节点都在同一层。

当插入节点过多使得路数大于M时,就要将节点拆分,将中间节点升为父节点,两边为左右子节点。

B+树

B+树是B树的升级版,也是平衡多路查找树。查询速度完全接近于二分查找。

1、 **B+层级更少,**树非叶子节点不存储数据,只做数据的索引,所以B+树每个节点能够存储的关键字数量更多;

2、 **B+查询查询更稳定,**叶子节点保存了非叶子节点的全部数据,所有的数据必须查找到叶子节点,所以查询次数都一样;

3、 **B+树天然具备排序功能,**b+树所有叶子节点数据构成了一个有序链表,在查询数据的时候查询大小区间更方便,数据更紧密,缓存的命中率也会更高;

4、 **B+树全节点遍历更快,**B+树所有数据都存在叶子节点中,如果需要遍历全部节点,只需要遍历全部叶子节点即可,有利于全表扫描;

B树的有点相对而言是:如果访问的数据经常位于根节点附近,那么检索数据就会比B+快,因为B树本身非叶子节点也保存了数据。

带权哈夫曼树的构造

循环队列的相关条件和公式:

队尾指针是rear,队头是front,循环队列的长度为m

1、队空:rear == front

2、满:(rear + 1) % m == front

3、当前队列长度:(rear – front + m)% m

4、入队列:(rear + 1)% m

5、出队列:(front + 1)% m

跳表

首先链表有序,取出链表中间隔的元素,然后组成第二链表,这样第二链表相比于第一链表就少了一半元素,在查询时先查询第二链表如果有差相应的原始链表的位置,速度增加了一倍,以此类推可以出现第三链表,第四链表……,直到链表中就剩两个元素为止。

计算机网络

杂知识

Ping命令发出的请求为ICMP请求报文。

A类网络地址开头为0(0000 0000),b类为10(1000 0000),c类为110(1100 0000),d类为1110(1110 0000)

网络体系结构

OSI七层结构

物理层,数据链路层,网络层,运输层,应用层,会话层,表示层;

TCP/IP四层结构

网络接口层,网际层(IP),运输层(TCP/IP),应用层(FTP,Telnet,SMTP)

折中的便于学习的五层协议

物理层,数据链路层,网络层,运输层,应用层

各层的作用

应用层:提供应用程序的网络接口;

传输层:提供两个主机之前的数据传输,提供端到端的服务;

网络层:通过怎么样的路线到达目的主机,即寻址和路由选择;

数据链路层:处理链接网络的硬件的部分,访问物理介质,传输有地址的桢以及错误检查

物理层:接口和线缆。

网络协议

数据链路层:VPN
网络接口层:Wi-Fi、ATM 、GPRS、EVDO、HSPA

网络层:IP,ICMP,ARP,IGMP

传输层:TCP、UDP

应用层:FTP,Telnet,SMTP,HTTP

ARP:由IP地址到MAC地址;

RARP:由MAC地址到IP地址

工作在各个网络层的仪器

物理层:中继器和集线器

数据链路层:交换机

网络层:路由器(用于分组转发)

滑动窗口发送消息

停止等待协议:发送窗口和接收窗口大小为1(一次发一个,等待确认后发送)

后退N桢协议:发送窗口>1,接收窗口=1(发送窗口不需等待确认直接发送,如果在确认超时时间内没有找到,返回到该桢发送后序所有包)

选择重传协议:发送窗口>1,接收窗口=1(与后退N桢类似,不同的是接收端没有收到某个桢的话发送端只会发送这个桢不会倒退发送所有后续桢)

三次握手四次挥手

三次握手

1. 应用端发送 **SYN(1)包和seq(client_isn(自身的客户端标识))**连接请求,

2. 服务端收到请求后发送SYN(1)包和seq(server_isn(自身的服务端标识))和ACK(client_isn+1)包,连接允许

3. 客户端收到连接允许的请求后发送SYN(0)包和seq(client_isn+1(验证包))ACK(server_isn+1(验证包)) 连接成功

四次挥手

客户端请求关闭TCP连接时

1. 客户端发起关闭请求(FIN报文)

2. 服务端接收到客户端的关闭连接请求时发送一个ACK确认包(表明自己未发送完或者在确认自己是否发送完),此时客户端进入FIN_WAIT状态

3. 服务端确认自己发送完后发送给客户端一个FIN报文,表示可以关闭了(其中2,3,可以合并发送)

4. 客户端接收到报文后发送ACK告诉服务端关闭连接,然后进入了ACK_WAIT状态,在2MSL时间内没有收到服务端的未收到ACK回复,那么就会关闭TCP。

为什么连接3次,挥手4次

这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

常见状态码

200:请求成功;301:资源已经被永久移动;302:资源被临时移动;304:代表文档并未发生变化,请求成功但是无需请求;403:服务器拒绝请求(无权限等);404:资源找不到;505:服务器出错

退避算法

CSMA(载波监听多路访问)策略

1、1-坚持CSMA:一旦介质空闲,则发送数据,如果介质被占用,继续监听,直到介质空闲立即发送数据,如果有冲突就退避。

TCP和UDP的区别

1、 TCP面向连接,UDP面向无连接,传输之前就不需要建立连接。

2、 TCP的传输是点到点的,UDP支持一对一,一对多,多对一,多对多的传输

3、 Tcp提供可靠的数据连接,udp无法保证

4、 Tcp面向字节流,udp面向报文

5、 Tcp传输慢,udp传输快

6、 Tcp首部开销大一些20字节,udp8字节

7、 Tcp主要用于可靠地通信传输,比如电话等,udp主要用于广播等方面。

Tcp的可靠性如何保证

在Tcp中数据必须以正确的顺序到达对方,TCP对数据段进行了编号和确认ACK来实现可靠传输。TCP开始传输一个段是,为准备重传,而将该段放入到发送队列中,发送数据段同时启动时钟,如果收到了接收端的确认ack,那么就将数据段移除,如果在时钟过期后还没收到确认ack,那么就会重传该数据段。Tcp的连接通道和数据传输都需要两方的确认,所以非常可靠,在协议中还有分包,重组,重传等机制。

TCP对应的协议有:

FTP:文件传输协议,默认端口21;

Telnet:远程登录协议,默认端口23;

SMTP:邮件发送协议,默认端口25;

POP3:邮件接收协议,默认端口110

HTTP

UDP对应的协议有:

DNS:域名解析协议,默认端口53;

SNMP:网络管理协议,161端口

TFTP:简单文件传输协议,69端口

浏览器输入URL后发生了什么

1、 DNS解析域名

2、 NGINX转发代理

3、 建立TCP连接

4、 发送HTTP请求

5、 服务器处理请求

6、 返回响应结果

7、 关闭TCP连接

8、 浏览器解析HTML

9、 浏览器布局渲染

由子网掩码算多少位划分子网

子网掩码一共32位,前8位为网络号,后面24位用来划分子网,占用的个数即为划分子网的位数

例如子网掩码为255.255.255.240,划分子网使用的位数/p>

转为二进制位11111111 11111111 11111111 11110000,前8位为网络号不算在内,后面使用了20位划分子网。

操作系统

操作系统的特征:共享,并发,虚拟,异步

实时系统:任务必须在足够快的时间内完成,保证在限制时间内一定要完成。

分时系统:指多个用户同时使用一台计算机,具有多路性,交互性,独占性和实时性。

工作集:指某段时间间隔内,进程实际要访问的页面的集合。

虚拟存储技术:

1、 虚拟存储容量同时受计算机cpu位数和外存容量限制

2、 基于非连续分配技术

作业调度算法

FCFS(先来先服务);RR(时间片轮转);SJF(最短作业优先);

/p>

当进程分配到的页面数增加时,FIFO缺页中断产生的次数可能增加也可能减少

BIO、NIO、AIO

当你想去买个奶茶,然后看电影的时候,奶茶店没材料了,需要等候

Bio:同步阻塞。 然后就开始等,一直等到奶茶做好了再去看电影,做不好就一直等;

Nio:同步非阻塞。然后就我不等了,我先看会电影,但是呢你看一会就回来问问奶茶好了么/p>

Aio:异步非阻塞。然后我就不等了,看电影去了,你奶茶好了你给我送过来。

BIO在socket中ServerSocket,来一个连接就开启一个请求;

NIO就是基于Reactor,有流可读或可写时就通知引用程序处理

AIO就是AsynchronousSocketChannel(客户端异步读写),充分调用os。

Linux

进程间通信

UNIX套接字,信号量,(无名)管道,共享内存,消息队列,信号

常用命令

挂载系统目录并且只读的命令:mount -r /dev/sdb1 /tools (将/tools挂载到/dev/sdb1)

不能对目录创建软链接

Ext3日志文件系统的特点:高可用性

Top:监控电脑性能的命令(可用来获取cpu使用率)

$strong>获得上一条命令的返回码; 0 s h e l l 本 身 的 文 件 名 ; 0** shell本身的文件名;** 0/span>/span>shell/span>/span>! shell最后运行的后台process的PID;**$#**添加到shell的参数个数

./a.sh 子进程执行脚本;. ./a.sh当前线程执行脚本

2>&1 将标准错误输出到标准输出

&>file 将标准输出和标准错误输出重定向到文件中

找出某个文件所属的包(package): rpm -qf /etc/my.conf (以/etc/my.conf为例)

grep: 分析一行数据,如果找到需要的那么输出(ls -l | grep -I text,将ls -l结果中含有text的输出,不区分大小写)

**ps:**查看当前时刻进程运行情况

tail:查看文件的内容(tail -f file.txt,查看不断变化的txt文件)

du:显示文件或目录的大小

df:检查磁盘空间利用情况

运算符:

算术运算符:(expr不支持浮点运算,浮点运算需要用scale例如 echo “scale=2;3/4” | bc)

-eq 等于;-ne 不等于;-lt 小于;-le 小于或等于;-gt 大于;-ge 大于或等于([100 -ge ])

字符串运算符:(所有的比较必须放在“”中)

-z string 如果字符串长度为0,为真;-n string 如果字符串长度非0,则为真;

stirng1 != string2 是否不同; string1 == string2 是否相同;string1 < string2 按照字典顺序小于为真; string1 > string2 按照字典顺序大于为真

权限管理

使用ll可以查看文件权限命令(drwxrwxrwx,分为四个部分,第一个字母代表文件类型(常见的为-,表示普通文件),第2-4代表当前用户权限,5-7字母代表当前用户组权限,8-10代表其他用户权限)

Chmod权限命令

a 全部用户;u 用户; g 用户组; o 其他用户

+ 添加权限; – 减去权限;= 等于权限

r(4)可读;w(2)可写;x(1)可执行

(chmod 765 a.txt,给a.txt的权限为:当前用户rwx,当前用户组rw,其他用户:rx )

数据库

ACID

(一个事务正确可靠地四个条件)原子性,一致性,隔离性,持久性

事务的隔离级别

脏读(READ UNCOMMITTED)

未提交的事务进行的数据修改对其他事务都是可见的,如果一个事务读取到了其他事物未提交的数据,就是脏读。

不可重复读(READ COMMIT,大部分数据库隔离级别是这个,mysql不是)

一个事务开始时只能知道另一个事务已提交的修改,当事务A和事务B同时操作数据C,在事务A开始事务时,事务B保存了数据C,并在之后修改了数据C,这样就导致后来事务A发现数据不一致了,导致了不可重复读。

可重复读(REPEATABLE READ,mysql的默认事务隔离级别)

确保了同一个事务的多个实例在并发读取数据时,会看到相同的数据行。但是理论上可能会导致幻读:当用户在读取一个范围内的数据时,另一个用户在其中插入了一条数据,当用户再次读数据时,发现多了一行。Innodb通过MVCC机制解决了这个问题。

可串行化(SERIALIZABLE,最高的事务隔离级别)

通过强制事务排序,使之不可能产生冲突,从而解决幻读,给每个读都加上了锁。会有很多锁竞争情况。

MVCC机制(多版本并发控制)

范式

第一范式(1NF):每一个属性都不可再分,没有重复列或者重复组(比如地区:河南省,新乡市,唐龙公寓22号,不满足,可拆分为省,市,具体地址)

第二范式(2NF):每一个非主属性都完全依赖于候选码,不存在部分依赖

第三范式(3NF):每一个非主属性不能传递依赖于码,消除传递依赖

BF范式(BCNF):每一个决定因素中都有码,决定性因素子集中有码,消除任何属性对键的传递函数和部分函数依赖

索引

**最左前缀原则:**如果索引为联合索引,搜索树从左至右建立,如果最左边的字段没有,则搜索就不会用到索引。比如:索引为(A,B,C)那么:A,AB,ABC,AC会用到索引,AC只会用到A的索引部分,B,BC,C不会用到索引

如果查询的列在索引内(包括组合索引),那么就会走索引,如果是组合索引,会走全部长度的索引,即使部分索引属性没有查。

如果组合索引属性在条件语句里,就会遵守最左前缀。

DELETE和TRUNCATE TABLE都是删除表中的数据的语句,不同之处在于delete可以使用where指定删除条件,会返回删除条数,truncate table删除全部记录。

索引大致分为以下几个类别:普通索引,唯一索引,主键索引,全文索引

1、 索引加快了检索的速度

2、 索引降低了插入,删除,修改等维护的速度

3、 唯一索引可以确保每一行数据的唯一性

4、 使用了索引,在查询的时候可以使用到优化隐藏器,提高系统性能

5、 索引要占据物理和数据空间

唯一性约束

1、 唯一性约束用来限制不受主键约束的列上的数据的唯一性,用于作为访问某行的可选手段

2、 只要唯一就可以更新

3、 表中任意两行同一列不允许有重复值,可以为null

4、 一个表上可以有多个唯一性约束

唯一索引

创建唯一索引可以确保任何生成重复键值的尝试都会失败。

唯一性约束和唯一索引的区别

1、 约束是为了检查数据的正确性,索引是为了数据查询的优化

2、 创建唯一约束,会在该列创建一个constraint,同时会创建与约束对应的唯一索引,而唯一索引只会创建唯一索引,不会生成constraint

3、 在删除唯一约束时可以只删除约束而不删除索引,再删除索引时就可以插入重复值了

唯一索引和主键约束的的区别

1、 唯一性可以有null值,主键不可以

2、 都可以选择创建聚集索引或者非聚集索引,但是默认情况下,索引创建非聚集索引,主键创建聚集索引。

触发器

触发器指一段代码,当触发某个事件时,可以自动执行这些代码。MySQL中有6中触发器:before insert;after insert;before update;after update;before delete;after delete。

应用:通过监控数据进行级联删除;监控某个表数据根据更改进行相应的处理。

可以建立在表或者视图中

数据库引擎

InnoDB引擎

1、 默认事务引擎

2、 支持行级锁,外键,事务

3、 支持崩溃后的安全恢复

4、 数据存储在共享表空间

5、 对主键的查询性能高于其他引擎

6、 不支持全文索引

7、 叶子节点存放的是数据记录(聚集索引)

8、 叶子节点以主键聚集,所以必须有主键,辅助索引存储的不是数据记录而是对应的主键的值。

MyISAM引擎

1、 全文索引,压缩,空间函数

2、 不支持行级锁,外键,事务,使用的是表锁

3、 数据存储在文件中

4、 设计简单,在某些场景性能更高,如查询全文

5、 叶子节点存放的是数据记录的地址(非聚集索引),这样一来查询共有多少条等查询方式就很快

InnoDb的特性:

1、 插入缓存;

2、 二次写;

3、 自适应哈希索引;

4、 预读。

数据库的数据功能

数据定义功能:提供相应数据语言定义数据结构

数据操纵功能:对数据库的基本存取操作(检索,插入,修改,删除)

数据控制功能:对数据的完整性,并发性,完整性进行控制

视图

1、 视图是从一个或多个表中导出的虚表;

2、 一个用户可以定义若干个视图;

3、 视图可以用来定义新的视图

4、 视图可以提供数据的安全性

存储过程

1、 存储过程是一组T-SQL语句;

2、 存储过程预先被编译存放在服务器的系统中;

3、 存储过程可以完成某一特定的物理逻辑。

数据库优化

Mysql服务器优化

电脑本身的硬件优化,内存增大,或者window转linux

Sql本身优化

1、关联查询效率比关联子查询效率高很多

反范式设计优化

范式化设计增,删,改虽然会提高我们的效率,但是查找有时候会降低我们的效率,常见的情况是:本身牺牲一些空间多一些冗余字段,可以减少一个表,对于查找提升性能很多(以空间换时间)。

物理设计优化(字段类型,长度设计,存储引擎选择)

字段类型上(为表中数据选择合适的数据类型):

1、 优先考虑数字类型;

2、 其次是日期,时间类型;

3、 最后字符类型

4、 对于相同级别的数据类型,应优先选择占用空间小的数据类型

长度设计:选择适当的长度
存储引擎:根据不同的应用场景合理选择存储引擎

索引优化

以sql语句为 SELECT * from book ,索引为 pubindex(, , )为例

1、 范围查找放最后

如果有使用where age between 10 and 20 这样的语句,不会走索引,因为范围查找的索引放到了组合索引的前面。这个时候可以将索引改为:index(, ,)。

2、 索引的最左前缀原则

Index(a,b,c),查询时,a,ab,abc,ac会走索引,b或者bc不会走索引。

3、 能不使用就不使用

在查找时,如果没有用到索引,但是你只需要部分列,那么可以使用仅查找部分列,如果部分列都建立了索引,即使不是一个组合索引,也会使用到索引。比如:查询SELECT b_id, username, age from book where username=’21321’,此时会用到组合索引pubindex和主键索引b_id。

4、 In不走索引,or不走索引,between会走索引,and走索引

执行计划

根据执行计划分析sql的执行情况:使用explain查看执行计划,查询如下:

Possible_keys代表可能会用到的index,key代表查询中用到的index,key_len代表使用的index的长度

根据key_len计算使用的是哪个key/p>

对于varchar:

1、 utf-8编码 3字节

2、 varchar 2字节

3、 null 1字节

对于char:

1、 utf-8编码 3字节

2、 null 1字节

对于int:字段长度就是key_len长度

难点sql语句

1、获取年龄中最小的10-15个人(select * from user order by age limit 10,5)

虚拟机

类加载

静态代码块在类加载(初始化阶段运行)运行,且只执行一次,然后构造代码块和构造方法代码在每一次构造对象时都会运行,且构造代码块优先于构造方法。

JVM优化(常见问题处理方式)

1、 保存堆栈快照日志

2、 分析内存泄露原因

3、 调整内存设置

4、 控制垃圾回收频率

5、 选择合适的垃圾回收器

Spring

实现AOP的两种方式

动态代理:截取消息,对消息进行装饰,取代原有对象的执行

静态织入:我理解类似于告诉编译器,你需要把我加到编译后代码那段地方。

实现事务

1、 配置文件开启驱动,类和方法上加上Transactional,

2、 Spring启动的时候会解析生成相关的bean,查看拥有注解的类和方法,并且为这些类生成代理。

3、 真正的数据层的事务提交和回滚都是通过bin log和redo log实现的。

Springboot

集合(1.8)

ArrayList

Array扩容:空构造方法,初始为0,然后是10,之后1.5倍扩容。

Vector

与ArrayList相比,不同的是,vector是线程安全的,扩容方式是2倍(默认是两倍,如果设置了扩容因子,就是加上扩容因子)

LinkList

Linklist基于链表实现,双向链表结构。

HashMap

默认初始值是16,负载因子是0.75,当长度超过负载因子*length时,就会扩容为原来的2倍

1、 当链表的长度大于8时,链表将被替换为红黑树;

2、 当节点数量小于6时,红黑树还原成链表(不同的阈值是为了避免频繁树化和还原);

3、 只有当哈希表的值的数量大于64时,才会引发树化(否则元素多时会扩容而不是树化)。

4、 每次扩容扩容前元素都会再次计算存放位置,并重新插入。

容量是2的幂是因为,计算hash时可以通过&计算hash,与求模快,而且不易产生碰撞(长度16,length-1=15,二进制位1111,做&运算时碰撞率比14的1110小)

HashTable

初始值为11,扩容后:newSize=oldSize*2+1;

1、 key和value都不能为null;

2、 线程安全;

3、 在修改数据时使用synchronized锁住整张表,效率低。

ConcurrentHashMap

初始值16,超过0.75扩容。

1、 底层使用分段数组+链表+红黑树实现。

2、 线程安全。

3、 把Map分为了N(默认16)个段,采用锁分离技术提供相同的线程安全,但是效率提升了N倍,(它的读操作不加锁,值默认是volatile)

4、 它的synchronized不针对整张表,只锁住某个段,允许多个修改操作并发进行。

5、 只有size或者containValue方法才会锁住整张表。

6、 当空间不够时是在段内扩容,插入前检测容量,避免无效扩容。

HashMap和HashTable对比

1、 HashMap是非线程安全的,HashTable是线程安全的。

2、 HashMap的建和值可以是null,HashTable不能。

3、 HashMap非线程安全所以单线程环境下速度比HashTable快。

4、 1.5推出的ConcurrentHashMap是HashTable的替代品。

集合总结:

三种集合:list,set,map

List特点

1、存取有序,可重复,键和值可存入null

2、有三个实现类,ArrayList,linklist,Vector

3、ArrayList底层基于数组实现,支持随机访问,增删慢,查找快,效率高

4、linklist基于链表实现,不支持随机访问,增删快,查找慢

5、Vector基于数组实现,和ArrayList的区别是Vector是线程安全的。

Set特点

1、 存取无序,不可重复,不可存入null

2、 实现类:HashSet,LinkedHashSet,TreeSet(没有直接实现,先实现了sortset)

3、 HashSet由HashMap实现

4、 TreeSet底层由平衡二叉树实现

Map特点

1、存取无序,不可重复,不支持null(HashMap支持null)

2、Hashmap非线程安全,HashTable是线程安全的,ConcurrentHashMap是线程安全的

3、HashMap底层是数组+链表+红黑树

异常

异常的结构图:

异常结构图

最顶级的是:Throwable,

排序

快速排序平均速度最快

稳定排序的算法:冒泡排序,插入排序,归并排序,基数排序

非稳定排序算法:快速排序,选择排序,希尔排序,堆排序

设计模式

最能体现扩展性的是:装饰模式

适合解决对象间的依赖关系:观察者模式

Redis

一致性哈希算法

一致性哈希算法将空间分为一个环形空间,在环形空间里,每台机器结点被分布在环上不同的点,当key值被计算到某个点后,会顺时针寻找一个结点,数据会被保存在那里。当一个机器宕机了或者新添加了一个机器,也只会影响就近的一部分key,不会影响后面所有的key,这样尽可能的减少了删除或者新增机器对结点rehash带来的影响。这个特点解决了单调性和负载均衡的特性。

一致性哈希算法给每个机器结点虚拟出来了很多个虚拟结点,均匀的分布在环上,这样解决了平衡性,不会导致某个结点缓存过多key,而某些结点缓存过少key这样不平衡的情况。

性能优化

压测命令:./redis-benchmark -h 127.0.0.1,我的电脑上get和set100000条数据使用了133s

redis内存有限,跟电脑有关,64G或者128G

内存有限,可使用分库分表来增加内存,对不同的key取模进行分服务器存储

读多写少的情况下,使用读写分离来实现速度的优化

RESP协议

Redis的java客户端jedis与redis进行通信的通信协议。基于TCP应用层协议。

缓存穿透

原因:客户端多次查询一个不存在的key,导致每次都在缓存中查询不到,从而每次都到达数据库中查询。

解决方案

缓存空key

redis缓存这个不存在的key,值设置为null,当在数据库中查询不到的时候,redis一样缓存这个不存在的key,设置过期时间。

使用BloomFilter。

BloomFilter是一个可以判断这个key是否存在的组件,可以加载缓存之前,如果在bloomfilter中判断key不存在,直接返回null,如果存在就查缓存再查db。

两种方案对比

当客户端可能经常使用重复率高的不存在的key查询,我们可以使用第一种方案,

当客户端使用的不存在的key重复率低,那么使用第二种方案。

缓存击穿

原因:当多个线程同时请求一个key,但是这时key恰好失效了,这就导致一瞬间很多个请求同时请求数据库,数据库压力剧增。

解决方案

当有多个线程请求数据库时,就用互斥锁锁住请求,当第一个线程请求到了数据,那么可以将数据存进缓存,那么其他线程就可以直接使用缓存了。

缓存雪崩

原因:指某一时刻大量数据同时失效,例如当缓存服务突然宕机了,那么所有的请求都会直接请求到数据库,数据库可能承受不住。

解决方案

事前

使用集群缓存,保证缓存服务的高可用,在redis中,可以使用主从+哨兵,redis cluster来避免redis全盘崩盘的情况。

事中

ehcache本地缓存 + Hystrix限流&降级,避免MySQL被打死

事后

开启redis持久化机制,恢复内存中的数据。

热点数据失效

原因:我们在设置缓存时,经常会设置过期时间,当多个热点数据同时过期时,可能会出现很多个请求同时到达数据库,导致数据库压力增加。

解决方案

设置不同的失效时间

给不同的热点数据设置不同的失效时间,失效时间可以是某一个确定的时间+一个不确定的在一个小范围内波动的随机值。

互斥锁

和缓存击穿的方案类似,给请求的线程加锁,当第一个线程在数据库中请求到数据库,请求相同数据的线程就不会再到数据库中,但这样的方案会降低系统吞吐量。结合情况使用。

持久化

持久化有两种方式:RDB和AOF

RDB

原理:redis调用fork线程,子线程会把数据更改写到rdb文件中,覆盖旧文件,是一种快照形式的持久化方式

优点

1、rdb会配置时间点,在达到时间点时更改量到达要求的数据时就会开始持久化,比如save 60 100,在60s内更改量达到了100就进行备份,可以有多个时间点配置

2、采用子线程备份,不用影响主线程的继续服务

3、在数据量大的情况下,RDB相比AOF更快能启动

缺点

1、设置的时间点过长,可能导致redis宕机等时候在上次时间点至宕机时候数据未恢复

AOF

原理:比较可靠,当redis数据被修改时,就会把命令添加到aof文件中,当redis重启时,就会把aof文件重新执行一遍

杂知识

“ABCD”和“DBCA”比大小

**Static方法和变量不能被子类覆盖,**Son.staticmethod()或new Son().staticmethod()都是调用的子类的static方法,如果是Father.staticmethod()或者Father f = new Son(); f.staticmethod()调用的都是父类的static方法。

常见字符ASCII码

空格:32;0-9:48-57;大写字母:65-90;小写字母:97-122

变量相加的时候有类型提升:

1、 所有的byte,short,char值相加时会自动升级为int型,

2、 如果有一个操作数是long,那么结果为long

3、 如果有一个操作数为float,那么结果为float

4、 如果有一个操作数为double,那么结果为double

5、 如果操作数被声明了为final,会被jvm优化,不会类型提升。

基本类型所占字节数

boolean:1;char:2;byte:1;short:2;int:4;long:8;float:4;double:8

为什么lambda不能修改局部变量

因为lambda实质是匿名类,局部变量作为参数给lambda的时候,为防止lambda在用的时候局部变量已销毁,lambda拿的是变量的副本,所以不能修改。

Java的新特性(主要特性)

Java8

Lambda,stream编程,函数式接口

Java9

平台模块化系统,私有接口,集合的工厂方法, httpclient支持http2.0,改进了javadoc

Java11

局部变量类型推断,垃圾收集器(ZGC,停顿时间不超过10ms),http支持异步,inputstrean加强(transferto转为outputstream)

工具

Git

流程和常用流程的命令

常用命令和流程

Git工作流

git工作流

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91472 人正在系统学习中

来源:下雨了_简

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年5月3日
下一篇 2019年5月3日

相关推荐