├── javase ├── 反射面试题.md ├── 网络编程面试题.md ├── 常用类面试题.md ├── IO流面试题.md ├── 集合面试题.md ├── 面向对象面试题.md ├── 基本语法面试题.md └── 多线程面试题.md ├── project └── 架构设计面试题.md ├── 2019知识树.xmind ├── img └── logo │ └── logo.jpg ├── nosql └── NoSQL面试题.md ├── mq └── 消息中间件面试题.md ├── README.md ├── database └── 数据库面试题.md ├── resume └── 程序员的简历生存之道.md ├── distributed └── 分布式面试题.md ├── net └── 计算机网络面试题.md ├── framework └── 常用框架面试题.md └── jvm └── JVM面试题.md /javase/反射面试题.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /javase/网络编程面试题.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /project/架构设计面试题.md: -------------------------------------------------------------------------------- 1 | - [1. InnoDB中的事务隔离级别](#1-InnoDB中的事务隔离级别) 2 | -------------------------------------------------------------------------------- /javase/常用类面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 请说出常用的异常类型](#1-请说出常用的异常类型) 2 | ## 1.请说出常用的异常类型 3 | -------------------------------------------------------------------------------- /2019知识树.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienzhong/java-interview-guide/HEAD/2019知识树.xmind -------------------------------------------------------------------------------- /img/logo/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienzhong/java-interview-guide/HEAD/img/logo/logo.jpg -------------------------------------------------------------------------------- /javase/IO流面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 什么是java序列化,如何实现java序列化?Serializable接口的作用?](#1-什么是java序列化,如何实现java序列化?Serializable接口的作用?) 2 | - [2. FileInputStream 在使用完以后,不关闭流,想二次使用可以怎么操作?](#2-FileInputStream在使用完以后,不关闭流,想二次使用可以怎么操作) 3 | ## 1. 什么是java序列化,如何实现java序列化?Serializable接口的作用? 4 | 将一个java对象变成字节流的形式传出去称为序列化,从字节流中恢复一个对象称为反序列化。 实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable接口,该接口是一个mini接口,其中没有需要实现方法,implements Serializable只是为了标注该对象是可被序列化的。 5 | ## 2. FileInputStream在使用完以后,不关闭流,想二次使用可以怎么操作 6 | -------------------------------------------------------------------------------- /javase/集合面试题.md: -------------------------------------------------------------------------------- 1 | - [1. Collection和Collections的区别?](#1-Collection和Collections的区别?) 2 | - [2. ArrayList和LinkedList有什么区别?](#2-ArrayList和LinkedList有什么区别) 3 | - [3. HashMap,怎么扩容,怎么处理数据冲突?](#3-HashMap,怎么扩容,怎么处理数据冲突?) 4 | ## 1. Collection和Collections的区别? 5 | - Collection是一个接口,它是Set、List等容器的父接口; 6 | - Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。 7 | ## 2. ArrayList和LinkedList有什么区别 8 | ### 区别 9 | 1. ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。 10 | 2. 对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。 11 | 3. 对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。 12 | ### 性能差异 13 | 1. 对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。 14 | 2. 在ArrayList集合中添加或者删除一个元素时,当前的列表所所有的元素都会被移动。而LinkedList集合中添加或者删除一个元素的开销是固定的。 15 | 3. LinkedList集合不支持 高效的随机随机访问(RandomAccess),因为可能产生二次项的行为。 16 | 4. ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间 17 | ## 3. HashMap,怎么扩容,怎么处理数据冲突? 18 | HashMap底层数据结构是基于数组+链表的(1.8之后还引入了红黑树),Node数组的初始化长度为16,负载因子为0.75,HashMap所能容纳的最大数据量的Node(键值对)个数=Node数组初始化长度*负载因子,当HashMap所能容纳的最大数据量的Node个数大于Node数组初始化长度*负载因子的时候,会调用resize()方法进行扩容,扩容后的HashMap容量是之前容量的两倍。扩容的方法是创建一个新的数组替换原来的小数组,并把数据放入新数组。 19 | 20 | HashMap通过对key的hash值进行高位运算和取模来定位键值对的存储位置,有时两个key会定位到相同的位置,表示发生了Hash碰撞。比较两个key是否相等,如果相等直接覆盖原来key的值。 21 | -------------------------------------------------------------------------------- /javase/面向对象面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 面向对象的特征有哪些方面?](#1-面向对象的特征有哪些方面) 2 | - [2. 如何实现对象克隆?](#2-如何实现对象克隆?) 3 | - [3. 讲讲类的实例化顺序?](#3-讲讲类的实例化顺序,比如父类静态数据,父类构造函数,父类字段,子类静态数据,子类构造函数,子类字段,当new的时候,他们的执行顺序。?) 4 | ## 1. 面向对象的特征有哪些方面 5 | - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。 6 | 7 | - 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。 8 | 9 | - 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。 10 | 11 | - 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。 12 | ## 2. 如何实现对象克隆? 13 | 有两种方式: 14 | 1. 实现Cloneable接口并重写Object类中的clone()方法; 15 | 2. 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。 16 | 17 | 注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。 18 | ## 3. 讲讲类的实例化顺序,比如父类静态数据,父类构造函数,父类字段,子类静态数据,子类构造函数,子类字段,当new的时候,他们的执行顺序。 19 | 类的实例化顺序:先静态再父子 20 | 21 | 父类静态数据->子类静态数据->父类字段->子类字段->父类构造函数->子类构造函数 22 | -------------------------------------------------------------------------------- /nosql/NoSQL面试题.md: -------------------------------------------------------------------------------- 1 | - [1. Memcache和Redis的区别](#1-Memcache和Redis的区别) 2 | - [2. 为什么Redis能这么快](#2-为什么Redis能这么快) 3 | - [3. 说说你用过的Redis的数据类型](#3-说说你用过的Redis的数据类型) 4 | - [4. 如何通过Redis实现分布式锁](#4-如何通过Redis实现分布式锁) 5 | - [5. Redis中大量的key同时过期的注意事项](#5-Redis中大量的key同时过期的注意事项) 6 | - [6. 如何使用Redis做异步队列](#6-如何使用Redis做异步队列) 7 | ## 1. Memcache和Redis的区别 8 | - Memcache 9 | - 支持简单数据类型 10 | - 不支持数据持久化存储 11 | - 不支持主从 12 | - 不支持分片 13 | - Redis 14 | - 数据类型丰富 15 | - 支持数据磁盘持久化存储 16 | - 支持主从 17 | - 支持分片 18 | ## 2. 为什么Redis能这么快 19 | - 完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高 20 | - 数据结构简单,对数据操作也简单 21 | - 使用多路I/O复用模型,非阻塞IO 22 | - 采用单线程,单线程也能处理高并发请求,想多核也可以启动多实例 23 | ## 3. 说说你用过的Redis的数据类型 24 | - String:最基本的数据类型,二进制安全 25 | - Hash:String元素组成的字典,适合用于存储对象 26 | - List:列表,按照String元素插入顺序排序 27 | - Set:String元素组成的无序集合,通过Hash表实现,不允许重复 28 | - Sorted Set:通过分数来为集合中的成员进行从小到大的排序 29 | - 用于计数的HyperLogLog(非重点,前面五个尽量说出来) 30 | ## 4. 如何通过Redis实现分布式锁 31 | SET key value [EX seconds] [PX milliseconds] [NX|XX] 32 | - EX seconds:设置键的过期时间为second秒 33 | - PX milliseconds:设置键的过期时间为millisecond毫秒 34 | - NX:只在键不存在时,才对键进行设置操作 35 | - XX:只在键已经存在时,才对键进行设置操作 36 | - SET操作成功完成时,返回OK,否则返回nil 37 | ## 5. Redis中大量的key同时过期的注意事项 38 | - 现象: 39 | - 集中过期,由于清楚大量的key很耗时,会出现短暂的卡顿现象 40 | - 解决方案 41 | - 在设置key的过期时间的时候,给每个key加上随机值 42 | ## 6. 如何使用Redis做异步队列 43 | 使用List作为队列,RPUSH生产消息,LPOP消费消息 44 | - 缺点:没有等待队列里面有值就直接消费 45 | - 解决方案: 46 | - 可以通过在应用层引入Sleep机制去调用LPOP重试 47 | - BLPOP key [key ...] timeout:阻塞直到队列有消息或者超时,缺点是只能供一个消费者消费 48 | - pub/sub:主题订阅者模式,缺点:消息的发布是无状态的,无法保证可达 49 | -------------------------------------------------------------------------------- /mq/消息中间件面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 说说RabbitMQ的结构](#1-说说RabbitMQ的结构) 2 | - [2. RabbitMQ交换器种类](#2-RabbitMQ交换器种类) 3 | - [3. RabbitMQ队列与消费者的关系](#3-RabbitMQ队列与消费者的关系) 4 | - [4. 如何保证消息的顺序性](#4-如何保证消息的顺序性) 5 | ## 1. 说说RabbitMQ的结构 6 | 1. Brocker:消息队列服务器实体。 7 | 2. Exchange:消息交换机,用于接收、分配消息。指定消息按什么规则,路由到哪个队列。 8 | 3. Queue:消息队列,用于存储生产者的消息。每个消息都会被投入到一个或者多个队列里。 9 | 4. Binding Key:绑定关键字,用于把交换器的消息绑定到队列中,它的作用是把exchange和queue按照路由规则binding起来。 10 | 5. Routing Key:路由关键字,用于把生产者的数据分配到交换器上。exchange根据这个关键字进行消息投递。 11 | 6. Vhost:虚拟主机,一个broker里可以开设多个vhost,用作不用用户的权限分离。 12 | 7. Producer:消息生产者,就是投递消息的程序。 13 | 8. Consumer:消息消费者,就是接受消息的程序。 14 | 9. Channel:信道,消息推送使用的通道。可建立多个channel,每个channel代表一个会话任务。 15 | ## 2. RabbitMQ交换器种类 16 | - Direct exchange(直连交换机):直连型交换机(direct exchange)是根据消息携带的路由键(routing key)将消息投递给对应队列的,步骤如下: 17 | 1. 将一个队列绑定到某个交换机上,同时赋予该绑定一个路由键(routing key) 18 | 2. 当一个携带着路由值为R的消息被发送给直连交换机时,交换机会把它路由给绑定值同样为R的队列。 19 | - Fanout exchange(扇型交换机):扇型交换机(funout exchange)将消息路由给绑定到它身上的所有队列。不同于直连交换机,路由键在此类型上不启任务作用。如果N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的发送给这所有的N个队列 20 | - Topic exchange(主题交换机):主题交换机(topic exchanges)中,队列通过路由键绑定到交换机上,然后,交换机根据消息里的路由值,将消息路由给一个或多个绑定队列。 21 | - 扇型交换机和主题交换机异同: 22 | 1. 对于扇型交换机路由键是没有意义的,只要有消息,它都发送到它绑定的所有队列上 23 | 2. 对于主题交换机,路由规则由路由键决定,只有满足路由键的规则,消息才可以路由到对应的队列上 24 | - Headers exchange(头交换机):类似主题交换机,但是头交换机使用多个消息属性来代替路由键建立路由规则。通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。 此交换机有个重要参数:”x-match”。 25 | - 当”x-match”为“any”时,消息头的任意一个值被匹配就可以满足条件 26 | - 当”x-match”设置为“all”的时候,就需要消息头的所有值都匹配成功 27 | ## 3. RabbitMQ队列与消费者的关系 28 | 1. 一个队列可以绑定多个消费者; 29 | 2. 队列分发消息将以轮询的方式分发,每条消息只会分发给一个订阅的消费者; 30 | 3. 消费者收到消息之后默认是自动确认,可以设置手动确认,保证消费者消费了消息。 31 | ## 4. 如何保证消息的顺序性 32 | - RabbitMQ 33 | 1. 拆分多个queue,每个queue一个consumer,就是多一些queue而已 34 | 2. 一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理 35 | - kafka 36 | 1. 一个topic,一个partition,一个consumer,内部单线程消费,写N个内存queue,然后N个线程分别消费一个内存queue即可 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 6 | [![QQ群](https://img.shields.io/badge/QQ%E7%BE%A4-82594417-blue.svg)](//jq.qq.com/?_wv=1027&k=5nTxYKs) 7 |
8 | 9 | 创建这个仓库的目的是根据自己工作以来学习积累的技术栈收集整理出一些具有代表性的面试题与知识点,方便自己查阅复习,也是为了以后自己能在面试中能够有出色的表现。也希望能帮助到大家学习与复习,面试通关,offer拿到手软~~ 10 | 11 | ## 目录 12 | - [:book: 简历](#book-简历) 13 | - [个人简历](#book-简历) 14 | - [:coffee: JavaSE](#coffee-java) 15 | - [基本语法](#coffee-JavaSE) 16 | - [面向对象](#coffee-JavaSE) 17 | - [常用类](#coffee-JavaSE) 18 | - [集合](#coffee-JavaSE) 19 | - [IO流](#coffee-JavaSE) 20 | - [多线程](#coffee-JavaSE) 21 | - [网络编程](#coffee-JavaSE) 22 | - [反射](#coffee-JavaSE) 23 | - [:car: JVM](#car-JVM) 24 | - [:rabbit: 消息中间件](#rabbit-消息中间件) 25 | - [:spider: 计算机网络](#spider-计算机网络) 26 | - [:apple: 数据库](#apple-数据库) 27 | - [:banana: NoSQL](#banana-NoSQL) 28 | - [:pig: 分布式](#pig-分布式) 29 | - [:cow: 常用框架](#cow-常用框架) 30 | - [:cat: 架构设计](#cat-架构设计) 31 | ## :book: 简历 32 | ### 个人简历 33 | * [程序员的简历生存之道](./resume/程序员的简历生存之道.md) 34 | ## :coffee: JavaSE 35 | ### 基本语法 36 | * [Java基本语法面试专题](./javase/基本语法面试题.md) 37 | ### 面向对象 38 | * [Java面向对象面试专题](./javase/面向对象面试题.md) 39 | ### 常用类 40 | * [Java常用类面试专题](./javase/常用类面试题.md) 41 | ### 集合 42 | * [Java集合面试专题](./javase/集合面试题.md) 43 | ### IO流 44 | * [IO流面试专题](./javase/IO流面试题.md) 45 | ### 多线程 46 | * [多线程面试专题](./javase/多线程面试题.md) 47 | ### 网络编程 48 | * [网络编程面试专题](./javase/网络编程面试题.md) 49 | ### 反射 50 | * [反射面试专题](./javase/反射面试题.md) 51 | ## :car: JVM 52 | * [JVM常见面试题系列](./jvm/JVM面试题.md) 53 | ## :rabbit: 消息中间件 54 | * [消息中间件面试专题](./mq/消息中间件面试题.md) 55 | ## :spider: 计算机网络 56 | * [计算机网络面试专题](./net/计算机网络面试题.md) 57 | ## :apple: 数据库 58 | * [数据库面试专题](./database/数据库面试题.md) 59 | ## :banana: NoSQL 60 | * [NoSQL面试专题](./nosql/NoSQL面试题.md) 61 | ## :pig: 分布式 62 | ### 微服务 63 | * [分布式面试专题](./distributed/分布式面试题.md) 64 | ## :cow: 常用框架 65 | * [常用框架面试专题](./framework/常用框架面试题.md) 66 | ## :cat: 架构设计 67 | * [常用框架面试专题](./project/架构设计面试题.md) 68 | -------------------------------------------------------------------------------- /database/数据库面试题.md: -------------------------------------------------------------------------------- 1 | - [1. InnoDB中的事务隔离级别](#1-InnoDB中的事务隔离级别) 2 | - [2. 解释下脏读、不可重复读、幻读](#2-解释下脏读、不可重复读、幻读) 3 | - [3. MyISAM和InnoDB两者之间的区别](#3-MyISAM和InnoDB两者之间的区别) 4 | - [4. 说说事务的四种特性(ACID)](#4-说说事务的四种特性(ACID)) 5 | 6 | ## 1. InnoDB中的事务隔离级别 7 | SQL标准中的事务四种隔离级别 8 | - 未提交读(Read Uncommitted):可能出现脏读(可能读取到其他会话中未提交事务修改的数据)、不可重复读、幻读 9 | - 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读) 10 | - 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读 11 | - 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞 12 | ## 2. 解释下脏读、不可重复读、幻读 13 | - 脏读:指当一个事务正字访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。 14 | - 不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。 15 | - 幻读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中) 16 | ## 3. MyISAM和InnoDB两者之间的区别 17 | InnoDB是一个事务型的存储引擎,支持回滚,设计目标是处理大数量数据时提供高性能的服务,它在运行时会在内存中建立缓冲池,用于缓冲数据和索引。 18 | - 优点: 19 | 1. 支持事务处理、ACID事务特性; 20 | 2. 实现了SQL标准的四种隔离级别; 21 | 3. 支持行级锁和外键约束; 22 | 4. 可以利用事务日志进行数据恢复。 23 | 5. 锁级别为行锁,行锁优点是适用于高并发的频繁表修改,高并发是性能优于 MyISAM。缺点是系统消耗较大。 24 | 6. 索引不仅缓存自身,也缓存数据,相比 MyISAM 需要更大的内存。 25 | - 缺点: 26 | 1. 因为它没有保存表的行数,当使用COUNT统计时会扫描全表。 27 | 28 | MyISAM 是 MySQL 5.5.5 之前的默认引擎,它的设计目标是快速读取。 29 | - 优点: 30 | 1. 高性能读取; 31 | 2. 因为它保存了表的行数,当使用COUNT统计时不会扫描全表; 32 | - 缺点: 33 | 1. 锁级别为表锁,表锁优点是开销小,加锁快;缺点是锁粒度大,发生锁冲动概率较高,容纳并发能力低,这个引擎适合查询为主的业务。 34 | 2. 此引擎不支持事务,也不支持外键。 35 | 3. INSERT和UPDATE操作需要锁定整个表; 36 | 4. 它存储表的行数,于是COUNT时只需要直接读取已经保存好的值而不需要进行全表扫描。 37 | 38 | 适用场景 39 | - MyISAM适合: 40 | 1. 做很多count 的计算; 41 | 2. 插入不频繁,查询非常频繁; 42 | 3. 没有事务。 43 | 44 | - InnoDB适合: 45 | 1. 可靠性要求比较高,或者要求事务; 46 | 2. 表更新和查询都相当的频繁,并且表锁定的机会比较大的情况 47 | ## 4. 说说事务的四种特性(ACID) 48 | 1. 原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可以只执行其中的一部分操作。 49 | 2. 一致性(Consistency):数据库总是从一个一致性的状态转到另一个一致性的状态。 50 | 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱加起来应该还得是5000,这就是事务一致性。 51 | 3. 隔离性(Isolation):通常来说,一个事务所做的修改在最终提交之前,对其他事务是不可见的。 52 | 4. 持久性(Durability):一旦事务提交,则其所做的修改就会永久的保存到数据库中。不会因为系统故障等情况而丢失所做的修改。 53 | -------------------------------------------------------------------------------- /resume/程序员的简历生存之道.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 自从毕业以后到现在,自己投递的简历不在少数,工作期间也看了不少程序员的简历。再经历了从求职者到招聘方的角色转变之后, 终于悟出了什么样的简历才算是好简历的一点心得体会,也明白了简历对于求职的重要性。 3 | 4 | 一份好简历会是一份好工作的敲门砖,一份好简历也是一门艺术,那我们就来研究研究这门艺术。 5 | ## 面试官是如何筛选简历? 6 | 俗话说“知己知彼,百战不殆”,求职也是一样,我们要知道我们的“敌人”是如何决定我们简历的生死,才能制定相应的策略去应对。 7 | 其实,面试官在筛选简历的时候可没你们想的那么敬业,而且很多面试官根本不是全职做面试工作,只是在工作之余来参与这份工作。但是,每天投递的简历的数量还是蛮多的,特别是一些大厂,多得你头皮发麻。试想一下,如果每份简历都去精读,那工作量不是要压死人?所以,在筛选简历的时候,面试官在每份简历上花费的时间其实只有十几二十秒,然后就决定了你简历的生死。 8 | 9 | 有些人会说,这么粗糙的挑选,很容易错过一些真正有实力的人。但是,事实就是这么残酷,所以,我们必须要在这一步旗开得胜! 10 | ## 如何吸引面试官的眼球? 11 | 通过前面说的,我们已经知道面试官筛选简历的时间非常短,那么如何在这十多二十秒的时间抓住面试官的眼球呢? 12 | ## 简洁明了 13 | 简历简历,其实全称可以理解为简单或者简洁的履历。其实我们投递简历就跟发传单类似,往往接传单的人扫一眼就决定了这个传单是否进入垃圾桶的命运。街上的传单是为商铺打广告,而我们的简历其实就是宣传自己的广告传单。你会发现,其实你在路上收到的传单几乎都是单页,为什么几乎都是单页的呢?因为商家明白,第一眼打动不了顾客,打印再多页也是徒劳。所以,我们的简历也是一样,不用整的那么多页,一页足矣,如果你的履历实在太丰富,也请不要超过两页! 14 | ## 突出优势 15 | 既然简历如此简短,那我们就更应该在有限的空间里最大化我们的优势。那该如何去做呢? 16 | 17 | ### 个人信息 18 | 这部分的内容必须如实填写,一般描述以下几项信息: 19 | - 姓名 20 | - 年龄 21 | - 手机 22 | - 邮箱:邮箱尽量不要用QQ邮箱,虽然我解决的无所谓,但是有些面试官会觉得你不专业,如果非要用QQ邮箱,也请不要用那种纯数字的,这似乎是很多面试官的潜规则。 23 | - QQ/微信:提供一个通过网络可以联系到你的方式 24 | - 工作年限 25 | ### 教育经历 26 | 如果你投递的公司比较注重学历和学校,且你的学历和学校都比较有优势,这一栏信息可以紧跟个人信息之后。但是如果你的学历和学校没有优势,把这一栏写在后面。 27 | 28 | 包含信息:学校名称 学历 专业 在校时间 29 | 30 | 比如:清华大学 本科 计算机科学与技术 2016-09~2020-07 31 | ### 开源项目和作品 32 | 这一栏的信息根据自己实际情况选择是否添加 33 | #### 开源项目 34 | 对于程序员来讲,没有什么比Show me the code能有说服力了 35 | 项目名:项目的简要说明,Star和Fork数多的可以注明 36 | #### 技术文章 37 | 挑选你写作或翻译的高质量的技术文章,如果转载或者阅读数量多可以标注出来 38 | #### 其他(比如有大型演讲或者参与大型技术活动的也可以写出来,没有则不写) 39 | ### 工作经历 40 | 工作经历按逆序排列,最新的在最前边。 41 | 42 | 通常简历的核心区域就是项目介绍,根据职位匹配需求,挑选出来的TOP3的项目 43 | 44 | #### A公司(2018年9月-2018年9月) 45 | ##### A项目 46 | - 项目背景上下文(场景、问题),可以适当减少项目具体的业务描述 47 | - 你在其中的角色(职责、发挥的作用、结果度量) 48 | - 与此项经历有关的知识与技能(技术栈) 49 | #### B公司(2018年9月-2018年9月) 50 | ##### A项目 51 | - 项目背景上下文(场景、问题),可以适当减少项目具体的业务描述 52 | - 你在其中的角色(职责、发挥的作用、结果度量) 53 | - 与此项经历有关的知识与技能(技术栈) 54 | 55 | **突出重点项目,按时间维度和与职位需求匹配度高低来区分,时间上越是近的且匹配度越高的越是详细写,而时间上比较远的可以略写,匹配度低甚至不沾边的就别写出来了 56 | 。另外,项目经历中无需写软件环境、硬件环境、开发工具之类的。我们在乎的是你会做什么菜(有什么技能和能力),而不关心你用的什么厨具 —— 菜刀、锅铲。**--来自公众号瞬息之间 57 | 58 | ### 专业技能 59 | - 专业技能要实事求是,不会的或者一知半解的千万不要写,不要为了拼凑技能而写了一大堆,不然,就算你简历通过了,面试的时候也会把你问懵的。 60 | - 少用精通这个字眼,如果你是真的精通,请无视我这条。因为一般被修饰为精通的技能一般都是面试官的重点照顾对象,所以,还是量力而行吧。 61 | - 专业名词一定要描述准确,注意大小写,比如GitHub不要写成github。很多时候,细节体现你的专业素养。 62 | ### 附加信息 63 | - 博客:持续输出高质量的技术文章 64 | - 开源:GitHub 持续 commit 65 | - 社区:有一定专业影响力的 66 | - 书籍:用心写的 67 | - 演讲:行业大会级别的 68 | - 论文:学术界比较有影响力的 69 | - 爱好:真正的兴趣点 70 | ## 锦上添花 71 | 前面我们已经讲了简历的内容,但是除了内容之外,简历也很注重外观。但是我所说的美化可不是让你搞一堆花哨的样式或者简历模板。我所说的外观就是简历的格式简洁明了,不要让样式的风采盖过了简历的内容。我们做的是技术,不是美工哦~ 72 | 73 | 还有一个需要说的就是简历的格式,很多人都会选择World文档,但是World文档你发给别人的时候很容易造成格式错乱,这样就影响了简历的阅读了。 74 | 75 | 我推荐使用PDF,美观且跨平台的兼容性强,阅读体验比较好哦! 76 | # 结语 77 | 以上就是我根据自己的经验和网上阅读过的博文总结出来的,我相信这一简历的生存周期会比其他简历更持久,但是有不足或者错误的地方也请大家多多指正。 78 | 79 | 最后祝大家旗开得胜,面试邀约不断,offer拿到手软~~ 80 | -------------------------------------------------------------------------------- /distributed/分布式面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 说说SpringCloud的工作原理](#1-说说SpringCloud的工作原理) 2 | - [2. Eureka的心跳时间](#2-Eureka的心跳时间) 3 | - [3. Eureka的缺点](#3-Eureka的缺点) 4 | - [4. eureka缓存存在什么地方](#4-eureka缓存存在什么地方) 5 | - [5. 说说分布式事务有哪些解决方案](#5-说说分布式事务有哪些解决方案) 6 | - [6. rpc和http的区别](#6-rpc和http的区别) 7 | ## 1. 说说SpringCloud的工作原理 8 | Spring Cloud是一个全家桶式的技术栈,包含了很多组件,其中比较核心的有Eureka、Ribbon、Feign、Hystrix、Zuul这几个组件。 9 | - Eureka是微服务架构中的注册中心,专门负责服务的注册与发现。每个服务中都有一个Eureka Client组件,这个组件专门负责将这个服务的信息注册到Eureka Server中。说白了,就是告诉Eureka Server,自己在哪台机器上,监听着哪个端口。而Eureka Server是一个注册中心,里面有一个注册表,保存了各服务所在的机器和端口号。服务调用者调用对应服务时,它的Eureka Client组件会找Eureka Server查找对应的服务信息进行调用,然后就可以把这些相关信息从Eureka Server的注册表中拉取到自己本地缓存起来,方便下次调用。 10 | - Eureka Client:负责将这个服务的信息注册到Eureka Server中 11 | - Eureka Server:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号 12 | - Feign基于动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求。Feign的一个关键机制就是使用了动态代理。 13 | - 首先,如果你对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理 14 | - 接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理,这是核心中的核心 15 | - Feign的动态代理会根据你在接口上的@RequestMapping等注解,来动态构造出你要请求的服务的地址 16 | - 最后针对这个地址,发起请求、解析响应 17 | - Ribbon的作用是负载均衡,会帮你在每次请求时选择一台机器,均匀的把请求分发到各个机器上。Ribbon的负载均衡默认使用的最经典的Round Robin轮询算法。而且,Ribbon是和Feign以及Eureka紧密协作,完成工作的。 18 | - 首先Ribbon从 Eureka Client里获取到对应的服务注册表,即知道了所有的服务都部署在了哪些机器上,在监听哪些端口号 19 | - 然后Ribbon就可以使用默认的Round Robin轮询算法,从中选择一台机器 20 | - Feign就会针对这台机器,构造并发起请求 21 | - Hystrix是隔离、熔断以及降级的一个框架,发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题 22 | - Zuul就是微服务网关,这个组件是负责网络路由的。一般微服务架构中都必然会设计一个网关在里面,像android、ios、pc前端、微信小程序、H5等等,不用去关心后端有几百个服务,就知道有一个网关,所有请求都往网关走,网关会根据请求中的一些特征,将请求转发给后端的各个服务。而且有了网关之后,可以做统一的降级、限流、认证授权、安全等功能。 23 | ## 2. Eureka的心跳时间 24 | - Eureka的客户端默认每隔30s会向eureka服务端更新实例,注册中心也会定时进行检查,发现某个实例默认90s内没有再收到心跳,会注销此实例。但是这些时间间隔是可配置的。 25 | - 不过注册中心还有一个保护模式,在这个保护模式下,他会认为是网络问题,不会注销任何过期的实例 26 | ## 3. Eureka的缺点 27 | - 不满足CAP的一致性 28 | - 停止维护了,2.0之后不开源 29 | ## 4. eureka缓存存在什么地方 30 | 31 | ## 5. 说说分布式事务有哪些解决方案 32 | - 基于XA协议的两阶段提交方案 33 | - 第一阶段是表决阶段,所有参与者都将本事务能否成功的信息反馈发给协调者;第二阶段是执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地在所有分支上提交或者回滚。 34 | - 缺点:两阶段提交方案锁定资源时间长,对性能影响很大,基本不适合解决微服务事务问题。 35 | - TCC方案 36 | - TCC方案其实是两阶段提交的一种改进。其将整个业务逻辑的每个分支显式的分成了Try、Confirm、Cancel三个操作。Try部分完成业务的准备工作,confirm部分完成业务的提交,cancel部分完成事务的回滚。 37 | - 事务开始时,业务应用会向事务协调器注册启动事务。之后业务应用会调用所有服务的try接口,完成一阶段准备。之后事务协调器会根据try接口返回情况,决定调用confirm接口或者cancel接口。如果接口调用失败,会进行重试。 38 | - 缺点:1、对应用的侵入性强。业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,应用侵入性较强,改造成本高。 39 | 2、实现难度较大。需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口必须实现幂等。 40 | - 基于可靠消息的最终一致性方案 41 | - 消息一致性方案是通过消息中间件保证上、下游应用数据操作的一致性。基本思路是将本地操作和发送消息放在一个事务中,保证本地操作和消息发送要么两者都成功或者都失败。下游应用向消息系统订阅该消息,收到消息后执行相应操作。 42 | - 消息方案从本质上讲是将分布式事务转换为两个本地事务,然后依靠下游业务的重试机制达到最终一致性。基于消息的最终一致性方案对应用侵入性也很高,应用需要进行大量业务改造,成本较高。 43 | - GTS 44 | - GTS是一款分布式事务中间件,由阿里巴巴中间件部门研发,可以为微服务架构中的分布式事务提供一站式解决方案。 45 | - 优点:性能超强、应用侵入性极低、完整解决方案、容错能力强 46 | ## 6. rpc和http的区别 47 | - RPC主要是基于TCP/IP协议,而HTTP服务主要是基于HTTP协议 48 | - RPC要比http更快,虽然底层都是socket,但是http协议的信息往往比较臃肿 49 | - RPC实现较为复杂,http相对比较简单 50 | - 灵活性来看,http更胜一筹,因为它不关心实现细节,跨平台、跨语言。 51 | - 如果对效率要求更高,并且开发过程使用统一的技术栈,那么用RPC还是不错的。 52 | - 如果需要更加灵活,跨语言、跨平台,显然http更合适 53 | -------------------------------------------------------------------------------- /javase/基本语法面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 是否可以从一个static方法内部发出对非static方法的调用](#1-是否可以从一个static方法内部发出对非static方法的调用) 2 | - [2. Integer与int的区别](#2-Integer与int的区别) 3 | - [3. 抽象类和接口有什么区别?](#3-抽象类和接口有什么区别) 4 | - [4. String、StringBuffer与StringBuilder的区别?](#4-String、StringBuffer与StringBuilder的区别) 5 | - [5. final, finally, finalize的区别?](#5-final,finally,finalize的区别) 6 | - [6. error和exception有什么区别](#6-error和exception有什么区别) 7 | - [7. Java中,throw和throws有什么区别](#7-Java中,throw和throws有什么区别) 8 | - [8. &和&&的区别?](#8-&和&&的区别?) 9 | - [9. switch能否用String做参数?](#9-switch能否用String做参数?) 10 | - [10. finalize()方法什么时候被调用?](#10-finalize方法什么时候被调用) 11 | - [11. 用最有效率的方法计算2乘以8?](#11-用最有效率的方法计算2乘以8?) 12 | ## 1. 是否可以从一个static方法内部发出对非static方法的调用 13 | 不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立。 14 | ## 2. Integer与int的区别 15 | int是java提供的8种原始数据类型之一,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。 16 | 17 | 在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。 18 | 19 | 在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。 20 | ## 3. 抽象类和接口有什么区别 21 | 1. 抽象类可以有构造方法,接口中不能有构造方法。 22 | 23 | 2. 抽象类中可以有普通成员变量,接口中没有普通成员变量 24 | 25 | 3. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。 26 | 27 | 4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。 28 | 29 | 5. 抽象类中可以包含静态方法,接口中不能包含静态方法 30 | 31 | 6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是publicstatic final类型,并且默认即为publicstatic final类型。 32 | 33 | 7. 一个类可以实现多个接口,但只能继承一个抽象类。 34 | ## 4. String、StringBuffer与StringBuilder的区别 35 | 1. String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象 36 | 37 | 2. StringBuffer和StringBuilder底层是 char[]数组实现的 38 | 39 | 3. StringBuffer是线程安全的,而StringBuilder是线程不安全的 40 | ## 5. final,finally,finalize的区别 41 | 1. final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型。 42 | 2. finally是异常处理语句结构的一部分,表示总是执行。 43 | 3. finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用. 44 | ## 6. error和exception有什么区别 45 | - Error(错误)表示系统级的错误和程序不必处理的异常,是java运行环境中的内部错误或者硬件问题。比如:内存资源不足等。对于这种错误,程序基本无能为力,除了退出运行外别无选择,它是由Java虚拟机抛出的。 46 | 47 | - Exception(违例)表示需要捕捉或者需要程序进行处理的异常,它处理的是因为程序设计的瑕疵而引起的问题或者在外的输入等引起的一般性问题,是程序必须处理的。 48 | 49 | - Exception又分为运行时异常,受检查异常。 50 | 51 | - 运行时异常,表示无法让程序恢复的异常,导致的原因通常是因为执行了错误的操作,建议终止程序,因此,编译器不检查这些异常。 52 | 53 | - 受检查异常,是表示程序可以处理的异常,也即表示程序可以修复(由程序自己接受异常并且做出处理), 所以称之为受检查异常。 54 | ## 7. Java中,throw和throws有什么区别 55 | - throw代表的是动作,throws是状态 56 | - throw用在方法中,而throws用在方法声明中 57 | - throw只能抛出一种异常,而throws可以抛出多个 58 | ## 8. &和&&的区别? 59 | - &运算符有两种用法:(1)按位与;(2)逻辑与。 60 | - &&运算符是短路与运算。 >如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。 61 | ## 9. switch能否用String做参数? 62 | 在 Java 7 之前, switch 只能支持byte,short,char,int 或者其对应的封装类,以及 Enum 类型。在JAVA 7中,String 支持被加上了。 63 | ## 10. finalize方法什么时候被调用? 64 | 在释放对象占用的内存之前,且对象的finalize()还没被垃圾收集器调用过,则垃圾收集器会调用对象的finalize()方法。 65 | 66 | ## 11. 用最有效率的方法计算2乘以8? 67 | 2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。 68 | -------------------------------------------------------------------------------- /javase/多线程面试题.md: -------------------------------------------------------------------------------- 1 | - [1. volatile关键字是否能保证线程安全?](#1-volatile关键字是否能保证线程安全?) 2 | - [2. Java中sleep()和wait()的区别](#2-Java中sleep和wait的区别) 3 | - [3. synchronized和lock的区别?](#3-synchronized和lock的区别?) 4 | - [4. 创建线程有几种不同的方式?你喜欢哪一种?为什么?](#4-创建线程有几种不同的方式?你喜欢哪一种?为什么?) 5 | - [5. 什么是线程?](#5-什么是线程?) 6 | - [6. 线程和进程有什么区别?](#6-线程和进程有什么区别?) 7 | - [7. Thread类中的start()和run()方法有什么区别?](#7-Thread类中的start()和run()方法有什么区别?) 8 | - [8. Java中Runnable和Callable有什么不同?](#8-Java中Runnable和Callable有什么不同?) 9 | - [9. Java中CyclicBarrier和CountDownLatch有什么不同?](#9-Java中CyclicBarrier和CountDownLatch有什么不同?) 10 | - [10. Java中interrupted和isInterrupted方法的区别?](#10-Java中interrupted和isInterrupted方法的区别?) 11 | - [11. 为什么wait和notify方法要在同步块中调用?](#11-为什么wait和notify方法要在同步块中调用?) 12 | - [12. 一般的线程优先级是什么回事,线程优先级高的线程一定会先执行吗?如果不设置优先级的话,那么线程优先级是多少,设置线程优先级用那个函数](#12-一般的线程优先级是什么回事,线程优先级高的线程一定会先执行吗?如果不设置优先级的话,那么线程优先级是多少,设置线程优先级用那个函数) 13 | ## 1. volatile关键字是否能保证线程安全? 14 | 否,volatile变量自身具有下列特性: 15 | 1. 可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。 16 | 2. 禁止进行指令重排序 17 | 3. 不保证原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种符合操作不具有原子性。 多线程共享变量的读写是通过主内存进行复制到线程本地内存中和把本地内存中值写入主内存中来实现的。 18 | 19 | 当写一个volatile变量时,JMM(Java内存模型)会把该线程对应的本地内存中的共享变量值刷新到主内存。 20 | 21 | 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从住内存中读取共享变量。 22 | ## 2. Java中sleep和wait的区别 23 | - 来自不同的类 : sleep来自Thread类,是Thread类的静态方法。而wait来自于object类。sleep是Thread的静态方法,那个线程调用的了sleep,那个线程就会休眠. 24 | - 持有锁:这一点很重要,sleep是没有释放锁的,使得该线程仍然占用这系统资源,wait方法则会释放锁,使得其他线程可以使用同步控制块或者方法。sleep 不释放系统资源并且有时间限制,需要调用sleep(milliseconds)来指定休眠时间 wait会释放资源,并且进入线程等待池等待,这个时候其他线程可以占用CPU,直到其他线程调用notify/notifyAll唤醒等待池中的线程,然后进入就绪队列等待系统分配资源 25 | - 使用范围: wait,notify,notifyAll只能在synchronized块中或者synchronied控制的方法中调用。而sleep可以在任何地方调用 26 | ## 3. synchronized和lock的区别? 27 | - 主要相同点:Lock能完成synchronized所实现的所有功能。 28 | - 主要不同点:Lock有比synchronized更精确的线程予以和更好的性能。 29 | 1. synchronized会自动释放锁,但是Lock一定要求程序员手工释放,并且必须在finally从句中释放。 30 | 2. synchronized修饰方法时,表示同一个对象在不同的线程中,表现为同步队列,如果实例化不同的对象,那么synchronized就不会出现同步效果了。 31 | ## 4. 创建线程有几种不同的方式?你喜欢哪一种?为什么? 32 | 四种方式可以用来创建线程: 33 | - 通过继承Thread类,优点:可以直接调用start方法启动。缺点:继承一个类后,不能再继承别的类。需要重写run方法。无返回值。 34 | - 实现Runnable接口,优点:可以实现多个接口或继承一个类;缺点:不能直接启动,要通过构造一个Thread把自己传进去。需要重写run方法,无返回值。 35 | - 实现Callable接口,优点:可以抛出异常,有返回值;缺点:只有jkd1.5以后才支持。需要重写call方法。结合FutureTask和Thread类一起使用,最后调用start启动。 36 | - 应用程序可以使用Executor框架来创建线程池,优点:非常高效的,很容易实现和使用。 37 | ## 5. 什么是线程? 38 | 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。 39 | ## 6. 线程和进程有什么区别? 40 | 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。 41 | ## 7. Thread类中的start()和run()方法有什么区别? 42 | start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。 43 | ## 8. Java中Runnable和Callable有什么不同? 44 | Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象. 45 | ## 9. Java中CyclicBarrier和CountDownLatch有什么不同? 46 | CyclicBarrier 和 CountDownLatch 都可以用来让一组线程等待其它线程。与 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。 CountDownLatch :允许一个或多个线程等待其他线程完成操作。 CyclicBarrier :同步屏障,它可以让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。 47 | ## 10. Java中interrupted和isInterrupted方法的区别? 48 | interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。 49 | ## 11. 为什么wait和notify方法要在同步块中调用? 50 | 主要是因为Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。 51 | ## 12. 一般的线程优先级是什么回事,线程优先级高的线程一定会先执行吗?如果不设置优先级的话,那么线程优先级是多少,设置线程优先级用那个函数 52 | -------------------------------------------------------------------------------- /net/计算机网络面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 说说TCP的三次握手](#1-说说TCP的三次握手) 2 | - [2. 谈谈TCP的四次挥手](#2-谈谈TCP的四次挥手) 3 | - [3. 为什么会有TIME_WAIT状态](#3-为什么会有TIME_WAIT状态) 4 | - [4. 服务器出现大量TIME_WAIT状态的原因有什么](#4-服务器出现大量TIME_WAIT状态的原因有什么) 5 | - [5. UDP的特点](#5-UDP的特点) 6 | - [6. TCP与UDP的区别](#6-TCP与UDP的区别) 7 | - [7. Http的主要特点](#7-Http的主要特点) 8 | - [8. Http请求/响应的步骤](#8-Http请求/响应的步骤) 9 | - [9. 在浏览器地址栏输入URL,按下回车之后经历的流程](#9-在浏览器地址栏输入URL,按下回车之后经历的流程) 10 | - [10. Http状态码](#10-Http状态码) 11 | - [11. Http常见状态码](#11-Http常见状态码) 12 | - [12. Get请求和Post请求的区别](#12-Get请求和Post请求的区别) 13 | - [13. Cookie与Session的区别](#13-Cookie与Session的区别) 14 | - [14. HTTPS数据传输流程](#14-HTTPS数据传输流程) 15 | - [15. HTTP与HTTPS的区别](#15-HTTP与HTTPS的区别) 16 | ## 1. 说说TCP的三次握手 17 | - 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。 18 | - 第一次握手:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认 19 | - 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态 20 | - 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务端进入ESTABLISHED状态,完成三次握手 21 | ## 2. 谈谈TCP的四次挥手 22 | - TCP采用四次挥手来释放连接 23 | - 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态 24 | - 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态 25 | - 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入到LAST_ACK状态 26 | - 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手 27 | ## 3. 为什么会有TIME_WAIT状态 28 | - 确保有足够的时间让对方收到ACK包 29 | - 避免新旧连接混淆 30 | ## 4. 服务器出现大量CLOSE_WAIT状态的原因有什么 31 | - 对方关闭socket连接,我方忙于读或写,没有及时关闭连接 32 | - 解决方案 33 | - 检查代码,特别是释放资源的代码 34 | - 检查配置,特别是处理请求的线程配置 35 | ## 5. UDP的特点 36 | - 面向非连接 37 | - 不维护连接状态,支持同时向多个客户端传输相同的消息 38 | - 数据包报头只有8个字节,额外开销较小 39 | - 吞吐量只受限于数据生成速率、传输速率以及机器性能 40 | - 尽最大努力交付,不保证可靠交付,不需要维持复杂的链接状态表 41 | - 面向报文,不对应用程序提交的报文信息进行拆分或者合并 42 | ## 6. TCP与UDP的区别 43 | 1. TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 44 | 2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付 45 | - Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。 46 | 47 | 3. UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。 48 | 4. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 49 | 5. TCP对系统资源要求较多,UDP对系统资源要求较少。 50 | ## 7. Http的主要特点 51 | - 支持客户端/服务端模式 52 | - 简单快速 53 | - 灵活 54 | - 无连接 55 | - 无状态 56 | ## 8. Http请求/响应的步骤 57 | 1. 客户端链接到Web服务器 58 | 2. 发送HTTP请求 59 | 3. 服务器接受请求并返回HTTP响应 60 | 4. 释放连接TCP连接 61 | 5. 客户端浏览器解析HTML内容 62 | ## 9. 在浏览器地址栏输入URL,按下回车之后经历的流程 63 | 1. DNS解析 64 | 2. TCP连接 65 | 3. 发送HTTP请求 66 | 4. 服务器处理请求并返回HTTP报文 67 | 5. 浏览器解析渲染页面 68 | 6. 连接结束 69 | ## 10. Http状态码 70 | - 1xx:指示信息--表示请求已接收,继续处理 71 | - 2xx:成功--表示表示请求已经被成功接收、理解、接受 72 | - 3xx:重定向--要完成请求必须进行更进一步操作 73 | - 4xx:客户端错误--请求有语法错误或请求无法实现 74 | - 5xx:服务端错误--服务端未能实现合法的请求 75 | ## 11. Http常见状态码 76 | - 200 OK:正常返回信息 77 | - 400 Bad Request:客户端请求有语法错误,不能被服务器所理解 78 | - 401 Unauthorized:请求未经授权 79 | - 403 Forbidden:服务器收到请求,但是拒绝提供服务 80 | - 404 Not Found:请求资源不存在 81 | - 500 Internal Server Error:服务器发生不可预期的错误 82 | - 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复 83 | ## 12. Get请求和Post请求的区别 84 | - GET在浏览器回退时是无害的,而POST会再次提交请求。 85 | - GET请求会被浏览器主动cache,而POST不会,除非手动设置。 86 | - GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 87 | - GET请求在URL中传送的参数是有长度限制的,而POST么有。 88 | - GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。 89 | - GET参数通过URL传递,POST放在Request body中。 90 | ## 13. Cookie与Session的区别 91 | - Cookie数据存放在客户的浏览器上,Session数据放在服务器上 92 | - Session相对于Cookie更安全 93 | - 若考虑减轻服务器负担,应当使用Cookie 94 | ## 14. HTTPS数据传输流程 95 | - 浏览器将支持的加密算法信息发送给服务器 96 | - 服务器选择一套浏览器支持的加密算法,以证书的形式回发浏览器 97 | - 浏览器验证证书合法性,并结合证书公钥加密信息发送给服务器 98 | - 服务器使用私钥解密信息,验证哈希,加密相应消息回发浏览器 99 | - 浏览器解密响应消息,并对消息进行验证,之后进行加密交互数据 100 | ## 15. HTTP与HTTPS的区别 101 | - HTTPS需要CA申请证书,HTTP不需要 102 | - HTTPS密文传输,HTTP明文传输 103 | - 连接方式不同,HTTPS默认使用443端口,HTTP使用80端口 104 | - HTTPS=HTTP+加密+认证+完整性保护,较HTTP安全 105 | -------------------------------------------------------------------------------- /framework/常用框架面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 说说Spring事务什么情况下才会回滚](#1-说说Spring事务什么情况下才会回滚) 2 | - [2. 说说Spring事务的传播属性](#2-说说Spring事务的传播属性) 3 | - [3. 说说Spring事务的隔离性](#3-说说Spring事务的隔离性) 4 | - [4. 说说Spring事务的特性](#4-说说Spring事务的特性) 5 | - [5. 说说你对SpringIOC容器的理解](#5-说说你对SpringIOC容器的理解)、 6 | - [6. 什么是Spring的依赖注入](#6-什么是Spring的依赖注入) 7 | - [7. IOC(依赖注入)方式](#7-IOC(依赖注入)方式) 8 | - [8. Springboot启动过程](#8-Springboot启动过程) 9 | - [9. 说说几个常用的注解](#9-说说几个常用的注解) 10 | - [10. spring的bean的生命周期](#10-spring的bean的生命周期) 11 | - [11. spring事件的实现原理,写出常用的几个事件](#11-spring事件的实现原理,写出常用的几个事件) 12 | ## 1. 说说Spring事务什么情况下才会回滚 13 | 当所拦截的方法有指定异常抛出,事务才会自动进行回滚。默认情况下是捕获到方法的RuntimeException异常,也就是说抛出只要属于运行时的异常(即RuntimeException及其子类)都能回滚;但当抛出一个不属于运行时异常时,事务是不会回滚的。如果是其他异常想要实现回滚,可以进行配置。 14 | ## 2. 说说Spring事务的传播属性 15 | 事务的传播性一般在事务嵌套时候使用,比如在事务A里面调用了另外一个使用事务的方法,那么这俩个事务是各自作为独立的事务执行提交,还是内层的事务合并到外层的事务一块提交那,这就是事务传播性要确定的问题。spring支持7种事务传播行为: 16 | 1. PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 17 | 2. PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。 18 | 3. PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。 19 | 4. PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。 20 | 5. PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 21 | 6. PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。 22 | 7. PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 23 | 24 | 备注:常用的两个事务传播属性是1和4,即PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW 25 | ## 3. 说说Spring事务的隔离性 26 | 事务的隔离性是指多个事务并发执行的时候相互之间不受到彼此的干扰。 27 | 28 | 事务的隔离级别也分为四种,由低到高依次分别为:read uncommited(读未提交)、read commited(读提交)、read repeatable(读重复)、serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。 29 | 1. read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。 30 | 2. read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。 31 | 3. repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。 32 | 4. serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻读。 33 | 5. DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别. 34 | ## 4. 说说Spring事务的特性 35 | 事务特性分为四个:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持续性(Durability)简称ACID。 36 | 1. 原子性(Atomicity):事务是数据库逻辑工作单元,事务中包含的操作要么都执行成功,要么都执行失败。 37 | 2. 一致性(Consistency):事务执行的结果必须是使数据库数据从一个一致性状态变到另外一种一致性状态。当事务执行成功后就说数据库处于一致性状态。如果在执行过程中发生错误,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这是数据库就处于不一致状态。 38 | 3. 隔离性(Isolation):一个事务的执行过程中不能影响到其他事务的执行,即一个事务内部的操作及使用的数据对其他事务是隔离的,并发执行各个事务之间无不干扰。 39 | 4. 持续性(Durability):即一个事务执一旦提交,它对数据库数据的改变是永久性的。之后的其它操作不应该对其执行结果有任何影响。 40 | ## 5. 说说你对SpringIOC容器的理解 41 | SpringIOC负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。 42 | ## 6. 什么是Spring的依赖注入 43 | 依赖注入,是IOC的一个方面。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。 44 | ## 7. IOC(依赖注入)方式 45 | - 构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。 46 | - Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。 47 | - 用构造器参数实现强制依赖,setter方法实现可选依赖。 48 | ## 8. Springboot启动过程 49 | - 构造SpringApplication的实例 50 | - 调用SpringApplication.run()方法 51 | - 构造SpringApplicationRunListeners 实例 52 | - 发布ApplicationStartedEvent事件 53 | - SpringApplicationRunListeners 实例准备环境信息 54 | - 创建ApplicationContext对象 55 | - ApplicationContext实例准备环境信息 56 | - 刷新的上下文 57 | ## 9. 说说几个常用的注解 58 | https://segmentfault.com/a/1190000014966727 59 | ## 10. spring的bean的生命周期 60 | 1. Spring 容器根据配置中的 bean 定义中实例化 bean。 61 | 2. Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。 62 | 3. 如果 bean 实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用 setBeanName()。 63 | 4. 如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。 64 | 5. 如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法。 65 | 6. 如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。 66 | 7. 最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。 67 | 8. 如果 bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。 68 | 9. 如果为 bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。 69 | > 我们这里描述的是应用Spring上下文Bean的生命周期,如果应用Spring的工厂也就是BeanFactory的话去掉第5步就Ok了。 70 | ## 11. spring事件的实现原理,写出常用的几个事件 71 | -------------------------------------------------------------------------------- /jvm/JVM面试题.md: -------------------------------------------------------------------------------- 1 | - [1. 说说你对JVM内存模型的了解,每个区的作用是什么?](#1-说说你对JVM内存模型的了解,每个区的作用是什么?) 2 | - [2. 什么是类的加载](#2-什么是类的加载) 3 | - [3. 类的生命周期](#3-类的生命周期) 4 | - [4. JVM对象分配规则](#4-JVM对象分配规则) 5 | - [5. JVM如何判断对象是否存活](#5-JVM如何判断对象是否存活) 6 | - [6. 介绍一下GC算法有哪些](#6-介绍一下GC算法有哪些) 7 | - [7. JVM有哪些垃圾回收器](#7-JVM有哪些垃圾回收器) 8 | - [8. JVM常用调优命令](#8-JVM常用调优命令) 9 | - [9. JVM常用性能调优参数](#9-JVM常用性能调优参数) 10 | - [10. Java内存模型中堆和栈的区别](#10-Java内存模型中堆和栈的区别) 11 | - [11. JVM中有几种类加载器](#11-JVM中有几种类加载器) 12 | - [12. 什么是双亲委派模型](#12-什么是双亲委派模型) 13 | - [13. 类加载过程](#13-类加载过程) 14 | - [14. 栈溢出的原因](#14-栈溢出的原因) 15 | - [15. 方法区溢出的原因](#15-方法区溢出的原因) 16 | ## 1. 说说你对JVM内存模型的了解,每个区的作用是什么? 17 | ### 栈区: 18 | 栈分为java虚拟机栈和本地方法栈 19 | 20 | 重点是Java虚拟机栈,它是线程私有的,生命周期与线程相同。 21 | 22 | 每个方法执行都会创建一个栈帧,用于存放局部变量表,操作栈,动态链接,方法出口等。每个方法从被调用,直到被执行完。对应着一个栈帧在虚拟机中从入栈到出栈的过程。 23 | 24 | 通常说的栈就是指局部变量表部分,存放编译期间可知的8种基本数据类型,及对象引用和指令地址。局部变量表是在编译期间完成分配,当进入一个方法时,这个栈中的局部变量分配内存大小是确定的。 25 | 26 | 会有两种异常StackOverFlowError和 OutOfMemoneyError。当线程请求栈深度大于虚拟机所允许的深度就会抛出StackOverFlowError错误;虚拟机栈动态扩展,当扩展无法申请到足够的内存空间时候,抛出OutOfMemoneyError。 27 | 28 | 本地方法栈为虚拟机使用到本地方法服务(native) 29 | 30 | ### 堆区: 31 | 32 | - 堆是被所有线程共享的一块区域,在虚拟机启动时创建,唯一目的存放对象实例。 33 | - 堆被划分成两个不同的区域:新生代(Young)、老年代(Old)。 34 | - 新生代又被划分为三个区域:Eden和两个幸存区(From survivor 和 To survivor)。 35 | - 新生代主要存储新创建的对象和尚未进入老年代的对象。老年代存储经过多次新生代GC(Minor GC)后仍然存活的对象。 36 | - 会有异常OutOfMemoneyError 37 | 38 | ### 方法区: 39 | 40 | - 被所有线程共享的区域,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。被Java虚拟机描述为堆的一个逻辑部分。有时候也称它为永久代(permanment generation) 41 | 42 | - 垃圾回收很少光顾这个区域,不过也是需要回收的,主要针对常量池回收,类型卸载。 43 | 44 | - 常量池用于存放编译期生成的各种字节码和符号引用,常量池具有一定的动态性,里面可以存放编译期生成的常量;运行期间的常量也可以添加进入常量池中,比如string的intern()方法。 45 | 46 | ### 程序计数器: 47 | 48 | - 当前线程所执行的行号指示器。通过改变计数器的值来确定下一条指令,比如循环,分支,跳转,异常处理,线程恢复等都是依赖计数器来完成。 49 | 50 | - Java虚拟机多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。为了线程切换能恢复到正确的位置,每条线程都需要一个独立的程序计数器,所以它是线程私有的。 51 | 52 | - 唯一一块Java虚拟机没有规定任何OutofMemoryError的区块。 53 | ## 2. JVM什么情况下会发生栈内存溢出 54 | 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。 55 | ## 3. 类的生命周期 56 | 类的生命周期包括这几个部分,加载、连接、初始化、使用和卸载 57 | - 加载,查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象 58 | - 连接,连接又包含三块内容:验证、准备、初始化。1)验证,文件格式、元数据、字节码、符号引用验证;2)准备,为类的静态变量分配内存,并将其初始化为默认值;3)解析,把类中的符号引用转换为直接引用 59 | - 初始化,为类的静态变量赋予正确的初始值 60 | - 使用,new出对象程序中使用 61 | - 卸载,执行垃圾回收 62 | ## 4. JVM对象分配规则 63 | - 对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。 64 | - 大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。 65 | - 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,知道达到阀值对象进入老年区。 66 | - 动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。 67 | - 空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。 68 | ## 5. JVM如何判断对象是否存活 69 | 判断对象是否存活一般有两种方式: 70 | - 引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。 71 | - 可达性分析(Reachability Analysis):从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,不可达对象。 72 | ## 6. 介绍一下GC算法有哪些 73 | GC最基础的算法有三种:标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般都采用分代收集算法。 74 | - 标记 -清除算法,“标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。 75 | - 复制算法,“复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。 76 | - 标记-压缩算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存 77 | - 分代收集算法,“分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。 78 | ## 7. JVM有哪些垃圾回收器 79 | - Serial收集器,串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿,只使用一个线程去回收。 80 | - ParNew收集器,ParNew收集器其实就是Serial收集器的多线程版本。 81 | - Parallel收集器,Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量。 82 | - Parallel Old 收集器,Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法 83 | - CMS收集器,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。 84 | - G1收集器,G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征 85 | ## 8. JVM常用调优命令 86 | Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo 87 | - jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。 88 | - jstat,JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。 89 | - jmap,JVM Memory Map命令用于生成heap dump文件 90 | - jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看 91 | - jstack,用于生成java虚拟机当前时刻的线程快照。 92 | - jinfo,JVM Configuration info 这个命令作用是实时查看和调整虚拟机运行参数。 93 | ## 9. JVM常用性能调优参数 94 | - Xss:规定了每个线程虚拟机栈的大小 95 | - Xms:堆的初始值 96 | - Xmx:堆能达到的最大值 97 | ## 10. Java内存模型中堆和栈的区别 98 | - 管理方式 99 | - 栈自动释放,堆需要GC 100 | - 空间大小 101 | - 栈比堆小 102 | - 碎片相关 103 | - 栈产生的碎片远小于堆 104 | - 分配方式 105 | - 栈支持静态和动态分配,而堆仅支持动态分配 106 | - 效率 107 | - 栈的效率比堆高 108 | ## 11. JVM中有几种类加载器 109 | 类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例;有以下几张类加载去: 110 | - 启动类加载器(Bootstrap ClassLoader):Java应用启动时,加载$JAVA_HOME/lib或 -Xbootclasspath指定的路径中的类文件; 111 | - 扩展类加载器(Extension ClassLoaser):由sun.misc.Launcher$ExtClassLoader实现,负责加载$JAVA_HOME/lib/ext或java.ext.dirs指定路径的类库; 112 | - 应用程序类加载器(Application ClassLoader):又称系统类加载器,由sun.misc.Launcher$AppClassLoader实现,是ClassLoader.getSystemClassLoader()的返回值。 113 | - 自定义类加载器需要继承抽象类ClassLoader,实现findClass方法,该方法会在loadClass调用的时候被调用,findClass默认会抛出异常。 114 | - findClass方法表示根据类名查找类对象 115 | - loadClass方法表示根据类名进行双亲委托模型进行类加载并返回类对象 116 | - loadClass方法表示根据类名进行双亲委托模型进行类加载并返回类对象 117 | ## 12. 什么是双亲委派模型 118 | - 双亲委托模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委托给父类加载器(父子关系由组合(不是继承)来实现)去完成,每一个层次的类加载器都是如此, 119 | 因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需要加载的类)时, 120 | 子加载器才会尝试自己去加载。 121 | - 使用双亲委托机制的好处是: 122 | - 避免同一个类被多次加载; 123 | - 每个加载器只能加载自己范围内的类; 124 | ## 13. 类加载过程 125 | 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking) 126 | 127 | ![](https://images.cnblogs.com/cnblogs_com/andy-zhou/806130/o_JVM001.png) 128 | 129 | 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。以下陈述的内容都已HotSpot为基准。 130 | ## 14. 栈溢出的原因 131 | - 是否有递归调用 132 | - 是否有大量循环或死循环 133 | - 全局变量是否过多 134 | - 数组、List、map数据是否过大 135 | ## 15. 方法区溢出的原因 136 | - 动态生成大量Class 137 | - 大量JSP或动态产生JSP文件(JSP第一次运行时需要编译为Java类) 138 | --------------------------------------------------------------------------------