知识点
链接:https://www.nowcoder.com/discuss/29890
1基础知识:
算法和数据结构
- 数组、链表、二叉树、队列、栈的各种操作(性能,场景)
- 二分查找和各种变种的二分查找
- 各类排序算法以及复杂度分析(快排、归并、堆)
- 各类算法题(手写)
- 理解并可以分析时间和空间复杂度。
- 动态规划(笔试回回有。。)、贪心。
红黑树、AVL树、Hash树、Tire树、B树、B+树。
图算法(比较少,也就两个最短路径算法理解吧)
计算机网络
OSI7层模型(TCP4层)
- 每层的协议
- url到页面的过程
HTTP
- http/https 1.0、1.1、2.0
- get/post 以及幂等性
- 区别 GET一般用于获取/查询资源信息,POST一般用于更新资源信息。
- http 协议头相关
- 网络攻击(CSRF、XSS)
TCP/IP
三次握手、四次挥手
拥塞控制(过程、阈值)
- 流量控制与滑动窗口
- TCP与UDP比较
- 子网划分(一般只有笔试有)
- DDos攻击
(B)IO/NIO/AIO
- 三者原理,各个语言是怎么实现的
- IO
- InputStream、OutputStream、Reader、Writer
- 阻塞IO、使用多个线程处理每一个请求、适用于请求请求量小且数据大的情况
- NIO
- ByteBuffer、Channel、Selector
- 非阻塞IO、使用单线程管理多个通道、适用于请求量大且数据小的情况
- IO
- Netty
- Linux内核select poll epoll
- 三者原理,各个语言是怎么实现的
数据库(最多的还是mysql,Nosql有redis)
- 索引(包括分类及优化方式,失效条件,底层结构)
sql语法(join,union,子查询,having,group by)
- Oracle分页 1234567SELECT * FROM(SELECT A.*, ROWNUM RNFROM (SELECT * FROM TABLE_NAME) AWHERE ROWNUM <= 40)WHERE RN >= 21
- Oracle分页
引擎对比(InnoDB,MyISAM)
数据库的锁(行锁,表锁,页级锁,意向锁,读锁,写锁,悲观锁,乐观锁,以及加锁的select sql方式)
- 锁相关内容
- 表级锁、行级锁、页级锁这三种是在锁的颗粒度上的对比
- 共享锁、排他锁是在锁的级别上来划分;
- 共享锁 SELECT …LOCK IN SHARE MODE; 当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。;
- 排他锁 SELECT …LOCK FOR UPDATE; 当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁
- 乐观锁、悲观锁 针对的是使用方式;
- 悲观锁 如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定。悲观并发控制主要用于数据争用激烈的环境
- 乐观锁 在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。乐观并发控制多数用于数据争用不大、冲突较少的环境中
- 隔离级别,依次解决的问题(脏读、不可重复读、幻读)
- DEFAULT 默认隔离级别,每种数据库支持的事务隔离级别不一样,如果Spring配置事务时将isolation设置为这个值的话,那么将使用底层数据库的默认事务隔离级别。顺便说一句,如果使用的MySQL,可以使用”select @@tx_isolation”来查看默认的事务隔离级别
- READ_UNCOMMITTED 读未提交,即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种,因此很少使用
- READ_COMMITED 读已提交,即能够读到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读
- REPEATABLE_READ 重复读取,即在数据读出来之后加锁,类似”select * from XXX for update”,明确数据读取出来就是为了更新用的,所以要加一把锁,防止别人修改它。REPEATABLE_READ 的意思也类似,读取了一条数据,这个事务不结束,别的事务就不可以改这条记录,这样就解决了脏读、不可重复读的问题,但是幻读的问题还是无法解决
- SERLALIZABLE 串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了
- 事务的ACID
- ACID是原子性(atomicity)
- 一致性(consistency)
- 隔离性(isolation)
- 持久性(durability)
- B树、B+树
- B-树
- 所有键值分布在整颗树中;
- 任何一个关键字出现且只出现在一个结点中;
- 搜索有可能在非叶子结点结束;
- 在关键字全集内做一次查找,性能逼近二分查找;
- B+ 树
- 所有关键字存储在叶子节点出现,内部节点(非叶子节点并不存储真正的 data)
- 为所有叶子结点增加了一个链指针
- 为什么使用B+树最为Mysql引擎
- B+树更适合外部存储,由于内节点无 data 域,一个结点可以存储更多的内结点,每个节点能索引的范围更大更精确,也意味着 B+树单次磁盘IO的信息量大于B-树,I/O效率更高。
- Mysql是一种关系型数据库,区间访问是常见的一种情况,B+树叶节点增加的链指针,加强了区间访问性,可使用在范围区间查询等,而B-树每个节点 key 和 data 在一起,则无法区间查找。
- 优化(explain,慢查询,show profile)
- 数据库的范式。
- 分库分表,主从复制,读写分离。
- Nosql相关(redis和memcached区别之类的,如果你熟悉redis,redis还有一堆要问的)
- memcached - 一致性Hash算法
- memcached - 一致性Hash算法
操作系统:
- 进程通信IPC(几种方式),与线程区别
- OS的几种策略(页面置换,进程调度等,每个里面有几种算法)
- 互斥与死锁相关的
- linux常用命令(问的时候都会给具体某一个场景)
- Linux内核相关(select、poll、epoll)
编程语言(这里只说Java):
- 把我之后的面经过一遍,Java感觉覆盖的就差不多了,不过下面还是分个类。
- Java基础(面向对象、四个特性、重载重写、static和final等等很多东西)
- 集合(HashMap、ConcurrentHashMap、各种List,最好结合源码看)
- 并发和多线程(线程池、SYNC和Lock锁机制、线程通信、volatile、ThreadLocal、CyclicBarrier、Atom包、CountDownLatch、AQS、CAS原理等等)
JVM(内存模型、GC垃圾回收,包括分代,GC算法,收集器、类加载和双亲委派、JVM调优,内存泄漏和内存溢出)
内存模型
- 程序计数器 它是当前线程所执行的字节码的行号指示器
- 虚拟机栈 生命周期和线程相同。每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。
- 本地方法栈 和虚拟机栈起的作用一样,只不过方法栈为虚拟机使用到的Native方法服务。虚拟机规范并没有对这个区域有什么强制规定,因此我们使用的HotSpot虚拟机,就干脆没有这块区域了,它和虚拟机栈是一起的。
- 堆 此内存唯一的目的就是存放对象实
- 方法区 存储虚拟机 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
哪些对象需要回收?
- 1、引用计数法
- 2、可达性分析法(一下列出GCROOT对象)
- 虚拟机栈中引用的对象
- 方法区中静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即Native方法)引用的对象
4种引用状态
- 强引用 代码中普遍存在的类似”Object obj = new Object()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象
- 软引用 描述有些还有用但并非必需的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。Java中的类SoftReference表示软引用
- 弱引用 描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java中的类WeakReference表示弱引用
- 虚引用 这个引用存在的唯一目的就是在这个对象被收集器回收时收到一个系统通知,被虚引用关联的对象,和其生存时间完全没关系。Java中的类PhantomReference表示虚引用
- 方法区回收
- 常量回收条件 当前系统中没有任何一处引用该常量
- 类回收条件
- 1、该类所有实例都已经被回收,也就是说Java堆中不存在该类的任何实例
- 2、加载该类的ClassLoader已经被回收
- 3、该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
- 垃圾回收算法
- 1、标记-清除(Mark-Sweep)算法
- 2、复制(Copying)算法
- 现在的商用虚拟机都采用这种算法来回收新生代
- 新生代的内存被划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。
- 3、标记-整理(Mark-Compact)算法
- 垃圾收集器
- 1、Serial收集器
- 反射和代理、异常、Java8相关、序列化
- 反射
- 1、反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- 2、作用:1在运行时判断任意一个对象所属的类;2在运行时构造任意一个类的对象;3在运行时判断任意一个类所具有的成员变量和方法;4在运行时调用任意一个对象的方法;5生成动态代理。
- 动态代理
- InvocationHandler JDK
- MethodInterceptor CGLIB
- 反射
- 设计模式(常用的,jdk中有的)
- Web相关(servlet、cookie/session、Spring
、Mybatis、Tomcat、Hibernate等) - Spring
- 依赖注入(DI) 反转控制(IOC) 面向切面编程(AOP)
- 1、创建被调用者工作由spring完成,注入调用者,称为依赖注入
- 2、反转控制指不通过调用者new被调用者,通过反射实现
- 3、AOP跟动态代理差不多,源代码无关性和各个步骤之间良好的隔离性
- 依赖注入(DI) 反转控制(IOC) 面向切面编程(AOP)
- Servlet
- 加载和实例化 在第一次请求Servlet时,Servlet容器将会创建Servlet实例
- 初始化阶段 调用init()方法
- 响应客户请求阶段 调用service()方法
- 终止阶段 调用destroy()方法
- DispatcherServlet作用
- 1、文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
- 2、通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
- 3、通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
- 4、通过ViewResolver解析逻辑视图名到具体视图实现;
- 5、本地化解析;
- 6、渲染具体的视图等;
- 7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
- 从以上我们可以看出DispatcherServlet主要负责流程的控制(而且在流程中的每个关键点都是很容易扩展的)。
- 8、DispatcherServlet重写了doService(抽象方法),doDispatch中通过mappedHandler进行方法定位
- Spring
项目经历
- 这个每个人的项目不同,覆盖的技术也不一样,所以不能统一去说。
- 这里的技巧呢,在下面也会详细说明。
- 无非是找到自己项目中的亮点,简历上叙述的简练并且吸引眼球,同时自己要很熟悉这个点(毕竟可以提前准备)
- 最好自己多练,就像有个剧本或者稿子一样,保证面试中可以很熟练通俗地讲出,并且让人听着很舒服。
其他扩展技能(这个方方面面太多了,全部掌握基本上不可能,只是作为大家其他时间扩充技能的参考)
分布式架构:(了解原理就行,如果真的有实践经验更好)
- CAP原理和BASE理论。
- CAP
- 1、Consistency(一致性), 数据一致更新,所有数据变动都是同步的
- 2、Availability(可用性), 好的响应性能
- 3、Partition tolerance(分区容错性) 可靠性
- CAP
- Nosql与KV存储(redis,hbase,mongodb,memcached等)
- 服务化理论(包括服务发现、治理等,zookeeper、etcd、springcloud微服务、)
- 负载均衡(原理、cdn、一致性hash)
- RPC框架(包括整体的一些框架理论,通信的netty,序列化协议thrift,protobuff等)
- 消息队列(原理、kafka,activeMQ,rocketMQ)
- 分布式存储系统(GFS、HDFS、fastDFS)、存储模型(skipList、LSM等)
- 分布式事务、分布式锁等
- 分布式锁
- 基于数据库表做乐观锁,用于分布式锁。
- 使用memcached的add()方法,用于分布式锁。
- 使用redis的setnx()、expire()方法,用于分布式锁。
- 使用redis的setnx()、get()、getset()方法,用于分布式锁。
- 分布式锁
- CAP原理和BASE理论。
大数据与数据分析:
- hadoop生态圈(hive、hbase、hdfs、zookeeper、storm、kafka)
- spark体系
- 语言:python、R、scala
- 搜索引擎与技术
机器学习算法:
- 模型和算法很多。不细说了,如果很熟练就去投算法,国内很多公司都算法岗都很稀缺,其他岗可以大概了解下理论。
其他工具的理论和使用:
- git、docker、maven/gradle、Jenkins