八股文一(基础篇、网络系列、生产问题)

基础篇

接口和抽象类的区别

相同:接口和抽象类都不能被实例化
不同:抽象类可以有构造方法,而接口没有

重载和重写的区别 *

重载:在一个类中,方法名相同、返回类型相同,参数不同,这就是重载。
重写:这发生在子类中,方法名相、参数列表、返回类型都相同,子类重写父类的方法。(但是final和private修饰的方法不可重写)

==和equals的区别 *

==比较基本类型,比较的是值,==比较引用类型,比较的是内存地址
equals是Object类的方法,有些类重写了equals方法,比较的是字符值

HashMap原理

在Jdk1.8之后基于数组+链表+红黑树来实现的,key不能重复,可以为null,线程不安全
(当链表长度大于8 并且数组长度大于64 变成红黑树)

当链表长度大于8 为什么变成红黑树?

因为在源码上有设置静态变量是8,上面注释解释是因为泊松分布,空间和时间的权衡后设置的值。

遍历HashMap有哪些方式

1.分别循环遍历key和value
2.迭代的方式
3.jdk8之后有了默认方法,forEach方法()
 maps.forEach((k,v)->{
 	System.out.println(k);
 	System.out.println(v);
 });

HashMap的扩容机制 *

数组初始化容量是16,默认的加载因子是0.75。
HashMap的扩展是HashMap用一个新的数组替换原来的数组。重新计算容量,向hashMap不停的添加元素,hashMap集合中存储的数据达到当前数组大小的75%则需要进行扩容,就创建一个大小为前一次两倍的新数组,也就是底层数组的长度总是2的n次方,以便装入更多的元素。当链表长度达到8,数据结构会变成红黑树,但数组长度没有超过64的时候,也会进行扩容。
(Node数组是HashMap静态内部类,也是HashMap里的数组)
(加载因子越靠近1,说明存的数据越多,越靠近0存的越少)

HashMap存取原理 *

1.首先根据key,通过哈希函数得到的hash值,进行二次hash,根据二次hash结果找到对应的索引位置。
2.如果这个位置有值,先进行equals方法比较,若结果为true则取代该元素,若结果为false,就将节点插入链表。

为什么HashMap底层数组的长度总是2的n次方

目的还是为了让哈希后的结果更均匀的分部,减少哈希碰撞,位运算的运算效率高于算术运算。

想要线程安全的HashMap怎么办?*

1 使用ConcurrentHashMap
2 使用HashTable
3 Collections.synchronizedHashMap()方法

ConcurrentHashMap如何保证的线程安全 *

JDK1.7: 使用分段锁,将一个Map分为了16个段,每个段都是一个小的hashmap,每次操作只对其中一个段加锁。
JDK1.8: 采用CAS+Synchronized,jdk8也保留到大数组segment,添加元素,首先判断容器是否为null,如果为null会使用volatile和CAS初始化,如果不为null会根据key计算出的该位置是否为null,也就是链表一个节点,如果为null,利用CAS设置该节点。如果不为null,就使用synchronized加锁,遍历或者添加数据。

(每次插入数据时判断在当前数组下标是否是第一次插入,是就通过CAS方式插入,然后判断f.hash是否=-1,是的话就说明其他线程正在进行扩容,当前线程也会参与扩容;删除方法用了synchronized修饰,保证并发下移除元素安全)

为什么ConcurrentHashMap集合中不允许存null的插入 *

HashMap是允许存入的,但ConcurrentHashMap不允许。
如果插入会报空指针异常,在源码添加方法第一句就判断是否null,如果为null就抛异常。
在单线程情况下,HashMap是可以通过containsKey(key)的方法来区分这个null值。
在多线程下,ConcurrentHashMap没有办法判断某一时刻值是null,还是压根就不存在,防止并发场景下的歧义问题。

HashTable与HashMap的区别 *

HashTable每个方法都用synchronized修饰,因此是线程安全的,但效率低。
HashTable的Key不允许为null,HashMap可以。
HashTable只对key进行一次hash,HashMap进行了两次Hash。
HashTable底层使用的数组加链表。

数组和链表的区别

数组:采用连续的存储元素进行存储数据,特点:查询快,插入慢
链表:是非连续打存储结构,特点:查询慢,删插快

ArrayList和LinkedList的区别 *

两者都不是线程安全
ArrayList的实现是基于数组,优点:查询快,插入慢。(数组在内存中是连续的地址,所以ArrayList查找数据更快)
LinkedList的实现是基于双向链表,优点:插入快,查询慢。(链表,在内存中是离散,不需要扩容,查找元素,从头遍历查询,所以查询慢)

如何保证ArrayList的线程安全?*

1.collentions.synchronizedList()
2.Vector (每个方法都由synchronized修饰,效率低)
3.juc下的CopyOnWriterArrayList
(不加锁,操作时为list创建一个副本,期间其它线程读取的都是原本list,写操作都在副本中进行,写入完成后,再将指针指向副本,保证线程安全)

String、StringBuffer、StringBuilder的区别 *

StringBuffer可变并且线程安全;
StringBuiler可变但线程不安全;
String是不可变的,每次操作String都会生成新的String对象,效率低。
(操作少量字符数据用 String;单线程操作大量数据用 StringBuilder;多线程操作大量数据用 StringBuffer)

hashCode和equals *

他们都是Object类的方法,hashCode()默认是用来计算hash码,
equals()默认通过地址判断两个对象是否相等,但是可能被重写用内容来比较两个对象。
如果:两个对象相等,他们的hashCode和equals一定相等,但是hashCode相等的两个对象未必相等,也就是重写equals()必须重写hashCode()。 

面向对象和面向过程的区别

面向对象有封装、继承、多态性的特性
面向过程易维护、易复用、易扩展。

多态的作用

多态的实现要有继承、重写,父类引用指向子类对象。目的就是降低耦合关系,提高扩充性和灵活性。

深拷贝和浅拷贝

浅拷贝只复制某个对象的引用,新旧对象还是共享同一块内存
深拷贝会创造一个一摸一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对对象。

什么是反射 *

反射是通过获取类的class对象,然后动态的获取到这个类的内部结构,动态的去操作类的属性和方法。

获取class对象的方法有 *

1 class.forName(类路径)
2 类.class()
3 对象的getClass()

Java创建对象得五种方式

1 使用new关键字
2 使用Class类的newInstance方法 (构造方法)
3 使用Constructor类的newInstance方法
4 使用反序列化
5 使用clone方法 (浅拷贝)

JDK 和 JRE 有什么区别

JDK(Java Development Kit),Java开发工具包
JRE(Java Runtime Environment),Java运行环境

final 在 java 中有什么作用?

用来修饰一个方法:无法被子类重写,但可以继承;
修饰类:无法被继承;
修饰一个引用:该值无法修改;

八种基本数据类型 *

byte、short、char、int、long、double、float、boolean

java 中 IO 流分为几种:

按流划分,可以分为输入流和输出流
按单位划分,可以分为字节流和字符流

BIO、NIO、AIO 有什么区别

同步阻塞BIO:一个连接一个线程
同步非阻塞NIO:它有一个缓冲区,一个请求来了,写到缓冲区内,该线程就不需要等待写完,他去处理其他事情了,它会一会回来看是否处理完
异步非阻塞AIO:它有一个缓冲区,一个请求来了,写到缓冲区内,该线程就不需要等待写完,他去处理其他事情了,等写完会通知该线程
例子:
BIO - 海底捞排队,怕过好一直等
NIO - 海底捞排队,出去逛商场,容易过号,或者回来还继续等
AIO - 海底捞排队,服务员会给你登记,你出去逛商场,有位置,服务员会叫你回来

网络系列

浏览器输入地址后做了什么

1 首先浏览器会根据域名查询ip地址,(DNS:获取域名对应的ip) 
2 浏览器向web服务器发送一个Http请求
3 服务器处理请求  
4 处理完返回HTML响应 
5 浏览器加载显示

状态码有哪些 *

1xx:请求正在处理
2xx:请求成功处理
3xx:请求重定向   301:永久重定向   302:临时重定向    304:使用本地缓存
4xx:客户端错误   400:请求格式错误  403:没有访问权限  415:请求体过大
5xx:服务端错误

TCP是什么

是一种面向连接的通信协议,不同但互连的计算机通依靠TCP提供可靠的通信服务。

TCP与UDP的区别 *

TCP是面向连接的传输协议; 可靠的,有状态,会记录哪些数据发送,哪些被拒绝。
UDP是面向无连接的传输协议;不可靠的,无状态。

什么是TCP网络分层

主要分应用层、传输层、网络互联层、网络访问层
分层的好处就是,各个层之间独立,不需要知道上下层是如何工作的;每层都要自己的职责,方便化标准化管理。
(应用层:根据什么(HTTP)协议组装数据包;
 传输层:创建TCP,有TCP头部信息;
 网络互联层:IP头部包含IP地址;
 网络访问层:以太网的信息,MAC地址信息)

三次握手的理解 *

客户端与服务器之间数据的发送的过程当中需要创建一个TCP,请求和响应都是数据包,在一个TCP的连接上是可以发送多个http请求的。
第1次握手:客户端发送一个带有SYN(synchronize)标志的数据包给服务端;
第2次握手:服务端接收成功后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了;
第3次握手:客户端再回传一个带有ACK标志的数据包,表示我知道了。
然后进行传输数据。

为甚要三次握手?

为了防止服务器端开启一些无用的连接增加服务器开销,
防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
( 为什么不使用两次握手:无法确认客户端是否真的想连接
   为什么不使用四次握手:三次握手已经足够,再多一次握手只会造成更多的连接时延 )

为甚要四次挥手?

第1次挥手:客户端发送一个带有FIN标志的数据包给服务端,告诉他我要关闭的;
第2次挥手:服务端收到后,会立刻返回给客户端,来告诉客户端我收到消息了,此时他的状态更改为即将要关闭状态。
第3次挥手:服务端也要关闭连接,他会再发生一个数据包给客户端,告诉客户端我也要关闭了。
第4次挥手:客户端收到后,会立刻返回给服务端,表示自己知道了。此时服务端收到后,服务端马上关闭连接。客户端这边它有一个定时器,等时间到了也关闭了连接。
为什么是4次,如果优化只能优化第2次和底3次合并一次,因为服务端在第2次的时候有些资源没有释放,第2次和第3次之间有延迟。
还有客户端这边如果没有收到服务端也要关闭连接(第3次挥手),客户端会重发第2次。来保证完成两端的相互确认,4次是最优的方案。

什么是洪泛攻击(SYN Flood)攻击?

客户端大量伪造IP发送SYN包,模拟第一次握手,服务端接收后,会响应目标地址,基本这些IP的客户端都会拒绝连接。此时这些大量IP在服务端存在一个队列中,处于半连接状态,如果队列满了,就处理不了正常的请求了。
解决:可以利用路由器的TCP拦截功能,使用STCP协议链接。

如何理解TCP的keep-alive的原理?

一个TCP连接,如果双方都不向对方发生数据,看是否出现死连接,判断对方是否失效,默认时间是7200秒,太长了,一般我们都使用心跳机制来判断。

http与https的区别 *

http是无状态的超文本传输协议,信息是明文传输。端口是80
https协议是由http+ssl协议,可进行加密传输、身份认证的具有安全性网络协议,端口是443。

讲一下telnet的用法

用法1:telnet是检查这个端口是否打开,用法:telnet ip地址 端口号 (来检查远端的服务器端口是否打开)
用法2:telnet模拟发送http请求,用法:telnet 域名 端口号

讲一下netstat的用法

用于显示各种网络相关信息
netstat -a   显示所有选项信息
netstat -at  显示tcp相关选项信息    同理utp是 netstat -au
netstat -l   显示正在监听的服务状态  netstat -lt  显示正在监听tcp的服务状态
netstat -r   显示路由信息

谈一下tcpdump

tcpdump 命令行抓包
tcpdump -i any host 目标ip地址 (通过这个命令监听包) - 可查看TCP连接过程3次握手、4次挥手
curl 目标ip地址 (手动访问)

生产问题

生产环境服务器变慢,诊断思路和性能如何分析 *

我们首先看服务器的性能,一般变慢的原因导致是:1CPU问题、2磁盘IO问题
1. 查看整机   命令:top (如果执行完命令,按1 会看到每个CPU信息)
   关注这几个属性: PID (进程id) %CPU(CPU占比) %MEM (内存占比)
   load average (系统的负载均衡): 0.07, 0.16, 0.22 分别为系统的1分钟 5分钟 15分钟  如果这3个值相加除以3 大于60,说明机器负载严重
2. 查看CPU   命令:vmstat 
   procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
   r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
   1  0 3902336 221428      0 455740    1    0     1     1    0    0  0  0 99  0  0
   详情:
   r:运行等待CPU时间片的进程数 (不超过CPU总核得2倍)   b :等待资源的进程数 
   us:用户进程消耗CPU的时间   (长时间在50%,程序需要优化)
   sy: 系统进程消耗CPU的时间   (us + sy)大于80% 代表CPU不足
   id:空闲的CPU占比
   查看某个进程的CPU的信息
   命令: ps -ef |grep java  得到进程id,再执行:pidstat -u 1 -p 进程id
3. 查看内存   命令:free -m
   详情:total (总量) used(使用中) free(还剩)   当 used/total 大于70%,需要加内存
   查看某个进程的内存信息
   命令: pidstat -p 进程id -r 2 (平均每2秒执行1次)
4. 查看硬盘   命令:df -h   
5. 查看磁盘I/O性能指标  命令: iostat -xdk 2 3 (2代表2秒钟执行1次 3代表执行3次)
    Device:  rrqm/s   wrqm/s  r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sda      1.76     1.27    0.52    1.26    18.81    17.52    40.92     0.00    2.28    1.08    2.78   0.28   0.05
    dm-0     0.00     0.00    0.17    0.94    10.35    11.18    38.91     0.00    1.36    1.73    1.29   0.29   0.03
    dm-1     0.00     0.00    2.12    1.59     8.46     6.34     8.00     0.05   12.37    0.81   27.80   0.06   0.02
   详情:
   rkB/s:每秒读取数据量kb            wkB/s:每秒写取数据量kb
   svctm:IO请求平均服务时间,单位毫秒  await:IO请求平均等待时间,单位毫秒(越小性能越好)
   util:一秒中有百分之几的时间用于IO操作,越接近100%,代表磁盘饱和,需要优化系统或者扩大磁盘
   查看每秒的IO读取情况信息
   命令: pidstat -d 2 -p 20998   可查看 kB_rd/s (每秒读速度)  kB_wr/s(每秒写速度)
6. 查看网络I/O网络流量  命令: ifstat 1 (1代表1秒钟执行1次,ifstat可能需要手动下载)
   查看各个网卡的in和out,观察负载情况,网络读写是否正常

生产环境服务器CPU占用率过高,谈谈分析思路

1.先用top命令找出CPU占比最高的
2.通过ps-ef 或jps,定位哪个进程CPU过高,命令:ps -ef |grep java 
3.定位具体线程或代码行数  
	命令:ps -mp 进程id -o THREAD,tid,time
	USER     %CPU PRI SCNT WCHAN  USER SYSTEM    TID     TIME
	root      1.0   -    - -         -      -      - 01:28:03
	root      0.0  19    - futex_    -      -  20998 00:00:00
	解释:
	TID(线程id) -m 显示全部的线程 -o 自定义参数格式	
4.将线程id转换为16进制格式(如果有英文需要小写)
	命令:printf "%x\n" 线程id
5.jstack进程,查询堆栈信息,可以得到哪些代码,那行有问题
	命令:jstack 进程id | grep 16进制格式线程id  -A60 (显示前60行代码)

JDK自带哪些JVM监控和性能分析工具有哪些

jinfo 这个命令可以查看JVM基本参数配置
jstack 打印JVM线程快照信息

GitHub操作

专业范围搜索:搜索内容 in:name:readme
搜索点赞超过500的内容:搜索内容 stars:>=500
学习搜索(代表搜索有组织写的学习类代码):awesome 搜索内容
高亮显示某行:url地址#L13-L20  (表示13-20行代码进行高亮)
项目搜索:快捷键 T
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值