面经八之牛客网面经整理


一、JUC多线程

1、HashMap源码
2、ArrayList源码
3、LinkedList源码
4、ConcurrentHashMap源码
10、阻塞队列实现
11、CopyOnWrite
12、线程池
14、线程间通信(无名管道,高级管道,命名管道,消息队列,Socket,共享内存,信号,信号量,)
15、写一个死锁的例子
19、Volatile,JMM,指令重排,Happens-before
Synchronized原理,偏向锁,轻量级锁,重量级锁
20、线程的状态;死锁
21、自动装箱,赋值操作,在内存里面是如何实现的
22、深拷贝浅拷贝
23、String类为什么是不可变的
24、ThreadLocal
25、Final/Static关键字的对象放在内存的什么位置
26、Java接口继承
27、CAS,存在的问题
28、CountDownLatch、Semaphore
29、动态代理
30、序列化反序列化,序列化底层实现
31、AIO, BIO, NIO
32、停止一个正在运行的线程
使用 interrupt()方法来中断线程有两种情况(阻塞/非阻塞)
// 非阻塞过程中通过判断中断标志来退出
// 阻塞过程捕获中断异常来退出
33、interrupted 和 isInterrupted 方法的区别
interrupted()是静态方法:内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态
isInterrupted()是实例方法,是调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态


二 、JVM虚拟机

1、反射就是把java各种成分(方法属性类)映射成一个个对象
2、JVM内存模型JMM内存模型
JVM(堆:对象,数组 元空间:静态类,静态常量,运行时常量 栈:基本数据类型、对象引用 本地方法栈 程序计数器:记录下一条需要执行的指令行)
内存溢出(Outofmemery):分配的空间不足以存放生成的对象
Stackoverflow:递归调用,内存泄露导致内存溢出
内存泄漏:已经不用的对象没有及时回收(被正在使用的类引用),单例模式引用类,网络通信资源未关闭,threadlocal
可达性分析: (GC Root有哪:本地方法对象;栈空间基本数据类型对象,引用对象;元空间常量对象,类对象,静态变量对象)
Finalize:调用时间不确定,垃圾回收器宣告对象死亡,两次标记,一次是gcroot引用链不可达,判断是否执行finallize方法;如果对象覆盖finallize未被引用放在FQ队列,方法执行随时可能终止,给与对象最后一次重生的机会
3、引用类型(强,软,弱,虚)
元空间和永久代:元空间使用本地内存,永久代使用jvm内存
字符串常量存放在永久代,容易内存溢出
类和方法信息大小难以确定,给永久代大小指定带来困难
永久代给GC带来麻烦
4、垃圾回收算法 (复制、标记清除、标记整理)
JVM老年代和新生代(2:1) 伊甸园区和幸存区(8:1:1)
YGC和FGC发生的具体场景;GC用什么垃圾回收器?回收过程?哪些部分可以用作GC root?
YGC发生在年轻代;FULLGC发生在老年代,发生情况:
老年代空间不足;永久代空间不足;调用System.gc等
5、垃圾收集器
年轻代收集器:Serial(单线程)、ParNew、parallel Scavenge
Serial/parnew:复制算法 以减少stop the world
Parrallel scavenge:复制算法 以增大吞吐率目标
老年代收集器: Serial Old (单线程)、Parallel Old、CMS(减少stop the world)
Serial Old(单线程):标记整理
Parallel Old(多线程,吞吐量优先):标记整理
CMS:标记清除
G1:复制 标记整理;并行与并发 分代收集 空间整合 可预测停顿
CMS 初始并发重新标记并发清除、
G1 初始并发最终标记筛选回收;gc 选择吞吐量响应 ClientServer
6、类加载机制,双亲委派模型,findClass和loadClass
7、类加载器:将.class文件加载到内存中运行
启动类:核心类加载
扩展类:家在扩展库javax
应用类加载:加载程序所在目录
自定义加载:定制化加载
(类的加载过程:加载(加载class文件生成类对象),链接(校验,准备,解析),初始化(执行变量赋值和静态代码块))
8、Class.forName和ClassLoader区别
Clossloader和clasforname都会将.class加载到jvm中,classforname还会执行static块,classloader不会
9、定位内存泄漏;性能调优参数(-xms -xmx -xss)
-xms 初始堆空间大小 -xmx最大堆空间 -xss每个虚拟机栈的大小
10、JVM 启动模式之 Client 与 Server(启动、区别编译器、gc、启动)
11、intern()


三、数据库

1、三大范式
2、ACID(持久性redolog.file,原子性)
(隔离(脏读:不同事物看到另一个事务未提交的数据)
(一致(不可重复读:数据在事务A提交之前被事务B修改提交,之后A读取的值和之前不一样))
(幻读:事务A在提交数据前事务B插入一行数据,在读取时发现多了一行,违背一致性)
InnoDB和MyISAM区别(Innodb索引和数据在一块,MyIsam数据和值分开;事务,主键,Inodb并发度高,适合写修改操作多)
3、索引(排好顺序的快速查找的数据结构)
4、B树和B+树的区别
B树随机查询 叶子非叶子结点都存放键和值 叶子节点各自稳定
B+树范围查询 顺序查询
非叶子节点存放键;叶子结点存放键和值 减少磁盘IO
叶子结点指向下一个叶子结点链表,查询效率稳定
哈希索引
底层哈希表,适合等值索引,无法范围查询,不支持索引排序
性能不稳定,发生哈希碰撞,退化成链表
5、为什么要用自增id作主键
6、内连接,外连接,左右外连接
左连接:select* from A left join B on ano=bno
内连接:select* from A inner join B on ano=bno
7、哈希索引,全文索引
8、前缀索引、聚簇索引、索引覆盖
9、索引什么时候失效
is null;slect *;like;>
=和in可以乱序
10、Explain(描述mysql如何执行查询操作,分析sql语句,查询低效原因)
慢查询-》explain分析(type(all),extra(usingfilesort,temporay))-》
Sql语句修改走索引)
Key_>primary
11、事务的隔离级别
12、事务和锁
13、MVCC
MVCC当前读和快照读
当前读(select for update,selsect in share mode,增删改)
快照读(不加锁的非阻塞读,select)
14、死锁(锁检测,锁超时 1、返回错误2、超时放弃3、部分回滚)
15、查询优化
16、主从复制,读写分离
17、sql
5select 2from 3where 4group by having 6order by 7limit
单表查询
select student_id,count(course_id),sum(score),course_id
from score
group by student_id
联合查询(内连接)
select student_id,stu.name,count(s.course_id),sum(s.score)
from score s,student stu
where s.student_id=stu.student_id
group by s.student_id
查询平均成绩大于60的同学平均成绩和id
Select student_id,avg(score)
From score
Group by student_id
Having avg(score)>60;


四、Redis

5种数据结构
有哪些好处
使用场景
数据淘汰策略
并发竞争问题
Redission分布式锁
持久化方式:RDB和AOF区别、优缺点
集群方案
数据分片模型
哈希槽
最大节点数为什么是16384个
Redis事务
性能优化常见方案
缓存击穿
缓存雪崩
对比memcache
Redis为什么是单线程的
lpush和brpop实现消息队列
应用场景
Redis线程模型
缓存和数据库双写一致性问题
如何解决redis的并发竞争key问题
MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据


五、计算机网络

1、 网络模型和协议
四层协议(应用层、传输层、网络层、网络接口层)
应用层(HTPP(使用TCP)、DNS(使用UDP)、SMTP、FTP、DHCP(UDP)):为计算机用户提供接口和服务
表示层:数据编码(加密解密、数据处理)
会话层:管理通信会话
传输层(TCP、UDP):管理端到端的通信连接(共享内存这些单机通信)
网络层(ICMP、IP、ARP):数据通信的光电物理特性(ARP键值映射:ip->MAC地址)
数据链路层(PPP):管理相邻接点的数据通行
物理层:数据通信的光电物理特性(连接不同的物理设备)
2、TCP和UDP的区别
udp无连接不可靠传输、面向报文、没有拥塞控制、首部开销很小
tcp点到点面向字节流连接,可靠传输,全双工协议
3、TCP、UDP、IP报文格式
TCP:源端口,目的端口,序号,确认号(确认号为N,N-1都收到了),校验和,窗口(允许对方发送数据量)
4、TCP三次握手四次挥手
为什么三次握手,不是两次:两次握手会导致已经失效的报文到达对方,引起 错误
四次挥手(1、客户端等待计时器为什么等待2msl2、客户端timewait和服务器端closewait):
1、最后一个报文没有确认,确保发送方的ACK可以到达接收方;2msl时间内没有收到,则接收方会重发
2、确保其他报文已经过期
5、TCP粘包
6、TCP 协议如何保证可靠传输: 序号、校验和、累计确认、超时重发、拥塞控制、选择重传
UDP如何保证可靠:累积确认 超时重传 滑动窗口
停止等待协议(超时重传协议):(超时定时器),超时重传
连续ARQ协议(自动重传请求): 批量发送,滑动窗口,累计确认
7、TCP的流量和拥塞控制
流量控制:(考虑点对点的通信量控制)接收方使用窗口大小控制发送方发送速率(死锁:坚持定时器)
拥塞控制:(拥控考虑整个网络)报文超时就是拥塞
1.慢启动算法:由小到大逐渐增加数据发送量,每收到一个确认就增加1(指数增长,慢启动阈值)
2.拥塞避免(慢启动到达阈值之后就会启动拥塞避免算法):
维护一个拥塞窗口的变量
只要网络不拥塞,就试探着调大拥塞窗口加1
8、ARQ协议
9、从浏览器中输入url之后发生了什么(HTTP工作过程)
DNS解析-》TCP连接-》发送HTTP请求-》服务器处理请求返回HTTP报文-》浏览器解析渲染页面-》连接结束
HTTP请求响应步骤
客户端连接web服务器-》发送HTTP请求-》服务器接收请求返回HTTP响应-》
释放连接TCP-》客户端浏览器解析HTML内容
10、DNS服务器基本流程(域名->ip)
缓存记录/根服务器-》本地服务器-》域名,加入缓存
11、http get(查)和post(增)的区别
HTTP报文层面:Get将请求信息放在URL,Post放在报文体中
数据库层面:get符合幂等性安全性,post不符合(幂等性是对数据库一次操作和数次操作是一致的)
其他层面:get可以被缓存、存储,post不行
12、cookies和session的关系
Cookie是服务器发送给客户端的信息,以文本信息存放在客户端
1、session 在服务器端,cookie 在客户端(浏览器)
2、session 相对于cookie更安全
3、考虑减轻服务器开销,使用cookie
13、服务器怎么知道客户端已经发送数据完毕?
14、数字证书、签名
数字证书:可信任组织颁发给特定对象的认证
数字签名:证明某个消息或者文件是可靠的
15、HTTP1.0、1.1、2.0之间的区别
HTTP1.0 短连接(每次处理一个请求) 无状态 支持c/s模式 简单快速灵活
HTTP1.1 长连接(一次tcp发送多个对象) 可抑制发送header
HTTP2.0 多路复用 数据压缩 服务器推送
16、HTTP缓存
17、http请求报文有什么?
请求(起始 请求方法 头部) Get 获取服务端资源
应答(起始行 状态码 头部) Post 提交数据到服务端
18、http和https
Http:tcp、ip 对称加密(明文) 无状态
Https: 非对称加密(密文) 申请证书 加入ssl层,保护交互数据隐私,提供对网站服务器身份认证(HTTPS=加密+认证+完整安全性)
19、http状态码
1xx:表示请求已接收,继续处理 200:请求成功接收
3xx:重定向 4xx: 客户端错误,有错误无法实现
5xx: 服务端错误
200:正常返回信息 400:客户端请求语法错误
403:服务器收到请求拒绝服务 404:资源不存在
500:服务器错误 503:服务器当前不能服务

六、 操作系统

1、进程、线程、协程(资源、调度、开销、健壮性、通信;包含、调度、
通信、保留状态)
2、进程间通信方 式 IPC(管道、命名管道、消息队列、共享内存、信号量、
套接字、信号)
3、进程调度算法(先来先服务、短作业优先、最短剩余时间优先、时间片
轮转、优先级调度、多级反馈队列、最高响应比占比)
4、死锁(概念、必要 条件、处理方法、银行家算法、活锁)
5、内存管理(内存完整性、安全、数据共享、SWAP)
6、I/O 管理(I/O 模式阻塞、非阻塞、多路复用、信号驱动、异步)


七、分布式相关

Paxos协议
Raft协议
ZAB协议
选举过程
基于zookeeper实现分布式锁
实现分布式发号器
分布式Barrier


八、还记得的算法题

1、零钱兑换
2、前缀树
3、打印菱形矩阵
4、随机数产生转换-根据(1,5)随机数生成器,生成(1,7)之内的随机数
5、LRU
6、k个一组反转链表
7、最长不重复子序串
8、连续子数和等于N
9、连续子数组最大和
10、快排
11、最大公因数
12、两个栈实现一个队列
13、股票买卖系列
14、topK
15、树层次遍历第一层从左往右,第二层从右向左
15、判断链表有环,求环的入口
17、两个链表找交点
18、合并k个链表
19、二叉树前序遍历
20、最长公共子序列
21、最长上升子序列
22、接雨水
23、二维接雨水


附录:

1、单例模式(饿汉式双端检索机制valatile)

加valatile的目的是进制指令重排,没有给对象初始化就赋值
        public class Singleton{
              private Sigleton(){}  
              private volatile static Singleton singleton=null;
              public static Singleton getInstance(){
              if(singleton==null){
                 Synchorized(Singleton.class){
                     If(singleton==null){
                     singleton=new Singleton();
                   }
               }
} 
return singleton; 
}  
}

2.二分查找

 //非递归方式
	public void binarySearch2(int a[],int val){
		int low =0;
		int high = a.length-1;
		int middle = 0;
		while(low<=high){
			 middle = (low+high)/2;
			if(val<a[middle]){
				//左边找
				high=middle-1;
			}else if(val>a[middle]){
				//右边找
				low=middle+1;
			}else{
		System.out.println("找到元素下标:"+middle);
				return;
			}
		}
		return;
	}

3、快排

public static void QuickSort(int arr[], int begin, int end){
     if(begin>end)  return; 
        int temp=arr[begin];
        int i=begin;
        int j=end;

        while(i<j){
            while(j>i&&arr[j]>=arr[begin]){
                j--;
            }

            while(j>i&&arr[i]<= arr[begin]){
                i++;
            }

            if(j>i) {
                int t = arr[i];
                arr[i] = arr[j];
                arr[j] = t;
            }
        }
        arr[begin]=arr[i];
        arr[i]=temp;
        QuickSort(arr,begin,i-1);
        QuickSort(arr,i+1,end);
    }

4、死锁

class lock1 implements Runnable{
  public void run(){
        synchronized(Main.l1){
            System.out.println("1:我获得了第一个锁");
            try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
            synchronized(Main.l2){
                System.out.println("1:我获得了第二个锁");
            }
        }
    }
}
 
class lock2 implements Runnable{
    public void run(){
        synchronized(Main.l2){
            System.out.println("2:我获得了第一个锁");
            try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
            synchronized(Main.l1){
                System.out.println("2:我获得了第二个锁");
            }
        }
    }
}
 
public class Main {
    public static String l1="lock1";
    public static String l2="lock2";
    
    public static void main (String[] args) {
        Thread lo1=new Thread(new lock1());
        Thread lo2=new Thread(new lock2());
        lo1.start();
        lo2.start();
       
    }
}

5、LRU缓存

class LRUCache {
    // key -> Node(key, val)
    private HashMap<Integer, Node> map;
    private DoubleList cache;
    // 最大容量
    private int cap;   
    public LRUCache(int capacity) {
        this.cap = capacity;
        map = new HashMap<>();
        cache = new DoubleList();
    }    
    public int get(int key) {
        if (!map.containsKey(key))
            return -1;
        int val = map.get(key).val;
        // 利用 put 方法把该数据提前
        put(key, val);
        return val;
    }
        public void put(int key, int val) {
        // 先把新节点 x 做出来
        Node x = new Node(key, val);
        if (map.containsKey(key)) {
            // 删除旧的节点,新的插到头部
            cache.remove(map.get(key));
            cache.addFirst(x);
            // 更新 map 中对应的数据
            map.put(key, x);
        } else {
            if (cap == cache.size()) {
                // 删除链表最后一个数据
                Node last = cache.removeLast();
                map.remove(last.key);
            }
            // 直接添加到头部
            cache.addFirst(x);
            map.put(key, x);
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值