博主太痛苦了,没有任何资源,一个人奋战着(可能别人家的孩子都有矿吧,嘤嘤嘤),对java面试也没有经验,对面试毫无经验,所以少吃了一餐饭,省下的钱买了份资料,我把它分享出来, 目的是想给和我一样没有任何资源,同时想在互联网混口饭吃的底层人员一些帮助。
话不多说,下面是正文
序言
我是一名在 IT 行业闯荡了 8 年的程序员,从最初刚毕业时的迷茫到找到一份工作的喜悦,从一个小白慢慢成长为一个行业老兵,从一个初创型的公司到一个几千人的大型互联网公司,从初级程序员到架构师、技术经理,回顾这 8 年来,也有许多可圈可点的地方。
最近几年公司的大小招聘,社招、校招都有参与,面试过许多大牛,也遇到过很多职场小白。有 10 年 工作经验的,也有刚刚毕业来面外包的、担任技术一面的面试官,深知技术面试之重要,来面试的不乏一轮游的,看着有些同学基础浮夸、做着重复的项目也没有任何总结沉淀,自我介绍完全不知道在说啥等等诸如此类的现状,这也让我非常苦恼,面试也很累的,一坐就大半天,聊十几二十个人,如果你还在东拉西扯不知所云,抑或是对面试官问的问题答非所问,基本在面试官心里已经给你 pass 掉了,之所以面试还在持续,只是因为职业素养罢了,为了不让面试者感觉太挫败,毕竟大老远的跑来求职都不容易,但是内心里却已经没有聊下去的欲望了。想想自己也是从那个层次一步步走上来的,也经历了许多坎坷,觉得有必要把我的面试经验跟大家分享一下,希望能帮助大家找到一份满意的工作。
面试需要有的放矢、机会是留给有准备的人。我相信经过你的努力,一定会有满意的收获。我挑出来面试官常问的知识点给大家有的放矢地强化,有助于快速提高,哪怕是临时抱佛脚也能跟面试官搭上话。
适宜阅读人群:
准备面试的初(中)级 Java 程序员或者面试官
文章分为八个部分,从 Java 基础、Java 核心、Java 进阶、Java 框架、分布式中间件、MySQL、JVM 到如何准备技术面试。先帮读者梳理知识点,这是我们的硬实力,打铁还需自身硬;然后我们还要有准备的去打好面试这场仗,无论是技术一面、二面 还是 HR 面试,都要认真准备,把自己的软实力也充分发挥出来,毕竟不是每个面试官都能一眼看透你的价值,你需要把发光点主动地表现出来。
下面开始进入主题。
一、Java 基础知识
1. 面向对象的特性有哪些?
封装、继承、多态。
还有一个抽象,问三个就说上面三个,问四个就再补一个抽象
2. Java 中 Override 和 Overload 有什么区别?
- 重写(Override):方法名、参数、返回值相同;子类方法
不能缩小父类方法的访问权限
,且只能比父类抛出更少的异常
;被覆盖的方法不能为 private
,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。 - 重载(Overload):
同一个类中
可以有多个名称相同的方法,但这些方法的参数类型、个数、顺序至少有一个不相同。
追问:什么情况下方法不能被重写?
方法被定义为 final
的时候不能被重写。
3. 抽象类和接口有什么区别?
抽象类:
- 抽象类使用
abstract
修饰; - 抽象类不能使用
new
关键字来实例化对象; - 抽象类可以含有抽象方法,也
可以不包含抽象方法
,抽象类中可以有具体的方法;
- 抽象类中的抽象方法只有方法体,没有具体实现。
接口:
- 接口使用
interface
修饰; - 接口不能被实例化;
- 一个类只能继承一个抽象类,但是可以实现多个接口;
- 接口中方法
均为抽象方法
; - 接口中方法是抽象方法,不能实现。
追问:什么情况下选择接口,什么情况下选择抽象类?
当要创建不带任何方法定义和成员变量的基类,应该选择接口;当有方法定义和成员变量的时候,应该选择抽象类。
4. JRE、JDK、JVM 有什么区别?
JRE
: Java 运行环境,为 Java 的运行提供了所需环境。JDK
: Java 开发工具包,提供了 Java 的开发环境和运行环境,JDK 包含 - JRE 还有 Java 编译器、Java 调试和分析工具等。JVM
是 Java 虚拟机,负责将 Java 字节码转换为机器码,正是 Java 能够跨平台的原因。它还提供了内存管理
、垃圾回收
和安全机制
等。
5. 值传递和引用传递有什么区别?
- 值传递:指的是在方法调用时,传递的参数是
按值的拷贝传递
,传递的是值的拷贝,也就是说传递后就互不相关了。 - 引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
6. JDK 中常用的包有哪些?
- java.
lang
:这个是系统的基础类; - java.
io
:这里面是所有输入输出有关的类,比如文件操作等; - java.
nio
:为了完善 io 包中的功能,提高 io 包中性能而写的一个新包; - java.
net
:这里面是与网络有关的类; - java.
util
:这个是系统辅助类,特别是集合类; - java.
sql
:这个是数据库操作的类。
7. 访问修饰符 public、protected、 default、private 的区别?
-
类的成员不写访问修饰符默认为
default
,默认对于同一个包的其他类相当于公开(public),对于不是同一个包的其他类相当于私有(private)。 -
受保护(protected)对子类相当于公开,对于不是同一个包没有父子关系的类相当于私有。
-
Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。
8. 数据基础类型有哪些?
基础类型有 8 种:byte、boolean、char、short、int、float、long、double,注意 String 不属于基础类型, 属于对象。
9. final 有什么用?
用于修饰类、属性和方法;凡是引用 final 关键字的地方皆不可修改!
- 修饰类:表示该类不能被继承;
- 修饰方法:表示方法不能被重写;
- 修饰变量:表示变量只能一次赋值以后,值不能被修改。
二、Java 核心知识
10. 常用的集合类有哪些?
最常用的集合类是 List 和 Map。List 的具体实现包括 ArrayList 和 Vector,它们是可变大小
的列表,比较适合构建、存储和操作任何类型对象
的元素列表。 List 适用于按数值索引
访问元素的情形。Map 提供了一个更通用
的元素存储方法。Map 集合类用于存储元素对(称作” 键” 和” 值”),其中每个键映射到一个值。
- Map 接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 等;
- List 接口的实现类主要有:ArrayList、LinkedList、Vector 等。
11. HashMap 和 Hashtable 有什么区别?
HashMap 运行 key 和 value 为 null
,而 Hashtable 不允许。Hashtable 是线程安全
的,而 HashMap 是非线程安全
的。
12. HashMap 的实现原理是什么?
HashMap 基于 Hash 算法
实现的,我们通过 put(key,value) 存储,get(key) 来获取。当传入 key 时,HashMap 会根据 key. hashCode()
计算出 hash 值
,存储时,如果出现 hash 值相同的 key,此时有两种情况,如果 key 相同,则覆盖原始值;如果 key 不同,即出现冲突,则将当前的 key-value 放入链表中。获取时,直接找到 hash 值对应的下标,在进一步判断 key 是否相同,从而找到对应值。
13. ConcurrentHashMap 的实现原理是什么?
ConcurrentHashMap 是 Java1.5
中引用的一个线程安全
的支持高并发
的 HashMap 集合类。该类包含两个静态内部类 HashEntry
和 Segment
,前者用来封装映射表的键值对
,后者用来充当锁的角色
。Segment 采用了非常精妙的“分段锁”策略
,每个 Segment 对应一个 HashEntry 数组,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁。
14. ArrayList 和 LinkedList 的区别是什么?
- ArrayList 的实现是基于
数组
,LinkedList 的实现是基于双向链表
; - 对于随机访问,ArrayList 优于 LinkedList;
- 对于插入和删除操作,LinkedList 优于 ArrayList,因为当元素被添加到 LinkedList 任意位置的时候,不需要像 ArrayList 那样重新计算大小或者是更新索引;
- LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
15. 如何实现 Array 和 List 之间的转换?
- Array 转 List:
Arrays. asList(array)
; - List 转 Array:List 的
toArray()
方法。
16. 在 Queue 中 poll() 和 remove() 有什么区别?
两者都是返回第一个元素,并在队列中删除返回的对象。不同的是如果没有元素 poll()
会返回 null
,而 remove() 会直接抛出异常
。
17. 哪些集合类是线程安全的?
Vector、Hashtable 都是线程安全
的,而 HashMap 是非线程安全
的,不过 Java. util. concurrent 并发包中,ConcurrentHashMap 是线程安全
的。
18. 什么是 Java 反射?
在 Java 运行时
环境中,对于任意一个类
,能够知道
这个类有哪些属性和方法
,对于任意一个对象
,能够调用
它的任意一个方法
。
19. Java 怎么实现动态代理?
Java 中,常用的动态代理实现方式有两种,一种是利用 JDK 反射机制生成代理
,另外一种是使用 CGLIB 代理
。JDK 代理必须要提供接口
,而 CGLIB 则不需要,可以直接代理类
,是基于继承当前类的子类实现的。
三、Java 必问专题
20. 进程和线程有什么区别?
- 进程:是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,
重点在系统调度和单独的单位
,也就是说进程是可以独 立运行的一段程序
。 - 线程:线程进程的一个实体,是
CPU 调度和分派的基本单位
,他是比进程更小的能独立运行的基本单位。
两者关系:一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程,资源分配给进程,同一进程的所有线程共享该进程的所有资源。
追问:GC(垃圾回收)知道吗?
垃圾回收线程是特殊的守护线程
,守护线程是运行在后台
的一种特殊进程。它独立
于控制终端并且周期性
地执行某种任务或等待处理某些发生的事件。
21. 创建线程有哪几种方式?
创建线程有三种方式:
- 继承
Thread
类重写run
方法; - 实现
Runnable
接口; - 实现
Callable
接口。
22. 什么是多线程,多线程的优劣?
多线程:多线程是指程序中包含多个执行流
,即在一个程序中可以同时运行多个不同的线程来执行不同的任务。
多线程的好处:
可以提高 CPU 的利用率
。在多线程程序中,一个线程必须等待的时候,CPU 可以运行其它的线程而不是等待,这样就大大提高了程序的效率。也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
多线程的劣势:
线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 多线程需要协调和管理,所以需要 CPU 时间跟踪线程; 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题。
- 你知道怎么创建线程池吗?
创建线程池的方式有多种,这里你只需要答 ThreadPoolExecutor 即可。
ThreadPoolExecutor() 是最原始的线程池创建,也是阿里巴巴 Java 开发手册中明确规范的创建线程池的方式。
24. 线程池的常用参数有了解吗?
ThreadPoolExecutor 包含以下七个参数:
- corePoolSize:线程池中的核心线程数
- maximumPoolSize:线程池中允许存在的工作线程的最大数量
- keepAliveTime:闲置超时时间
- unit:超时时间的单位(时/分/秒等)
- workQueue:线程池中的任务队列
- threadFactory:为线程池提供创建新线程的线程工厂
- rejectedExecutionHandler:线程池任务队列超过 maxinumPoolSize 之后的拒绝策略
前两个参数可以这么理解,如果运行的线程少于 corePoolSize,Executor 则可以不排队直接添加新的线程;如果大于等于 corePoolSize,则将请求加入队列,如果无法加入,则创建新线程;如果超出 maxinumPoolSize,任务被拒绝。
25. 怎么保证线程安全?
- 使用安全类,比如 Java. util. concurrent 下的类;
- 使用锁,例如 synchronized、Lock。
26. synchronized 和 Lock 有什么区别?
- synchronized 会自动释放锁,Lock 需手工释放锁(unlock() 方法释放锁),否则容易造成线程死锁;
- synchronized 是 Java 的关键字,在 JVM 层面上;Lock 是一个类;
- synchronized 无法判断是否获取锁的状态,Lock 可以判断是否获取到锁。
27. 什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。
追问:怎么避免?
- 加锁顺序,一个线程如果要获取多个锁,必须按照一定的顺序去获取;
- 加锁时限,一个线程尝试去获取锁,如果在指定的时间内获取不到,就放弃等待锁,并释放自己现在所持有的锁,然后随机等待一定时间,再去获取锁。
28. ThreadLocal 是什么?有哪些使用场景?
当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
ThreadLocal 的经典使用场景是 session 管理(不同的线程对应不同的 session)和数据库链接(为每个线程创建不同的链接)。
29. 你了解哪些设计模式?
- 创建型模式,共五种:简单工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。
- 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
30. 简单工厂模式和抽象工厂模式有什么区别?
- 简单工厂模式:是由一个工厂对象创建产品实例,简单工厂模式的类一般是使用静态方法,通过不同的参数的创建不同的对象实例,可以生产结构中的任意产品,不能增加新的产品。
- 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类,用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族。
四、Java 框架
31. Spring 框架的优点有哪些?
- Spring 提供 IoC 技术,控制反转,容器会帮你管理依赖的对象,将对象的创建交给了 Spring,简化了开发,降低了代码之间的耦合性和侵入性。
- Spring 提供了面向切片编程,这样对某一类的问题,比如日志,异常统一处理。
- Spring 提供了事务支持,我们只需通过配置就可以完成对事物管理。
- 集成各种优秀的框架,提供了对各种优秀框架如(Hibernate,MyBatis)等的直接支持。
32. 什么是 Spring AOP?
即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。主要体现在事务处理、日志管理、权限控制、异常处理等方面。
33. 什么是 Spring IoC?
即 inverse of control(控制反转),是 Spring 的核心,是一种创建对象的思想。将创建对象的权力交给 Spring 容器,其实就是让 Spring 容器帮你创建对象,而你不需要在 Java 代码中 new 对象了。
34. Spring 常用的注入方式有哪些?
- setter 注入
- 构造方法注入
- 注解注入
35. Spring 自动装配 bean 有哪些方式?
Spring 配置文件中 节点的 autowire 参数可以控制 bean 自动装配的方式:
- default:默认的方式和“no”方式一样
- no:不自动装配,需要使用节点或参数
- byName:根据名称进行装配
- byType:根据类型进行装配
- constructor:根据构造函数进行装配
36. @Autowired 是做什么用?
@Autowired 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 Spring 完成 bean 自动装配的工作。
37. Spring Boot 有什么优势?
Spring Boot 继承了 Spring 优点,使得开发更加方便快捷。
- 简化编码
- 简化配置
- 简化部署
- 提供了监控系统
- 上手快,开发效率高
38. Spring Boot 配置文件有哪几种类型?
配置文件有 . properties
格式和 . yml
格式,它们主要的区别是书法风格不同。
39. Spring Cloud 是什么?
Spring Cloud 是基于 Spring Boot 的一整套实现微服务的框架。它它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,提供了微服务开发所需的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等组件。
40. Spring Cloud 的核心组件有哪些?
- Eureka:服务注册和服务发现。
- Hystrix:断路器,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
- Zuul:网关,提供动态路由、监控、弹性、安全等边缘服务的框架。
- SpringCloudConfig:配置中心,配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置。
- SpringCloudBus:消息总线,用于在集群(例如,配置变化事件)中传播状态变化。
当然,除了以上还有很多,就不一一列举了。
41. MyBatis 和 Hibernate 的区别有哪些?
- 灵活性:MyBatis 更加灵活,MyBatis 可以进行更为细致的 SQL 优化。
- 可移植性: Hibernate 数据库移植性很好,MyBatis 的数据库移植性不好,不同的数据库需要写不同 SQL。
- 技术门槛:MyBatis 入门比较简单。
- 二级缓存: Hibernate 有更好的二级缓存机制,可以使用第三方缓存。MyBatis 本身提供的缓存机制不佳。
五、分布式系统基础中间件
42. ZooKeeper 是什么?
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
43. ZooKeeper 集群选主和同步的机制是什么?
ZooKeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步,实现这个机制的协议叫做 ZAB 协议。ZAB 协议有两种模式:分别是恢复模式和广播模式。
- 恢复模式,ZooKeeper 配置为集群模式时,系统启动或者是当前 Leader 崩溃或者是当前 Leader 丢失大多数的 Follower,ZK 进入恢复模式,恢复模式需要重新选举出一个新的 Leader,当领导者被选举出来,且大多数 Server 的完成了和 Leader 的状态同步以后,恢复模式就结束了。
- 广播模式,状态同步保证了 Leader 和所有 Server 都具有相同的系统状态。这时候当 Server 加入 ZooKeeper 集群后,会先在恢复模式下启动该 Server,发现 Leader 后,并和 Leader 进行状态同步,待到同步结束,它也参与消息广播,即进入广播状态。ZooKeeper 服务一直维持在 Broadcast 状态,直到 Leader 崩溃了或者 Leader 失去了大部分的 Followers 支持,才会进入恢复模式,从新选举 Leader。
44. 集群中有 3 台服务器,宕机 1 台,这个时候 ZooKeeper 还可以使用吗?
可以,根据选票过半的选举原则,因此集群节点最好为奇数;单数服务器只要没超过一半的宕机就可以继续使用;所以 ZooKeeper 集群的容灾数量 =(集群总节点数 - 1)/2;也就是说 3 台服务器集群的话,最多允许 1 台宕机。
45. Redis 是什么?都有哪些使用场景?
Redis 是一个使用 C 语言
开发的高效缓存内存数据库
。
Redis 使用场景:
- 缓存热点信息
- 缓存用户会话信息
46. 你使用过 Redis 的哪些常用功能?
- 数据缓存
- 分布式锁
47. Redis 支持的数据类型有哪些?
Redis 支持的数据类型:string、list、hash、set、zset(sorted set)。
48. Redis 和 Memcache 有什么区别?
- Redis 支持数据的持久化,而 Memcache 不行,因为 Redis 可以把数据持久化在硬盘,而 Memcache 只能放在内存。
- 支持的数据类型不同:Redis 有复杂的数据类型,Memcache 对数据类型支持相对简单。
- value 值大小不同:Redis 最大可以达到 512mb;Memcache 只有 1mb。
49. 什么是缓存穿透?怎么解决?
- 缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
- 解决方案:缓存空对象。如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
50. 缓存和数据库之间怎么保证双写一致性?
- 读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况,但串行化之后,就会导致系统的吞吐量会大幅度的降低,实际上一般不用这个办法。
- 读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应;更新的时候,先删除缓存,然后再更新数据库,可以使用事物机制来保证数据的一致性。然后还要合理的设置缓存过期时间。
51. Redis 持久化有几种方式?
- RDB(Redis Database):原理是将 Reids 在内存中的数据库记录定时 dump 到磁盘上的 RDB 持久化)。
- AOF(Append Only File):原理是将 Reids 的操作日志以追加的方式写入文件。
52. Redis 怎么实现分布式锁?
Redis 分布式锁一般使用 setnx(set if not exists)指令,只允许被一个程序占有,占用成功了就可以继续执行,失败了就只能放弃或稍后重试,使用完调用 del 释放锁。
伪代码示例(这里只是简述,实际应用没有那么简单的,感兴趣的同学可以详细查一下资料):
- 加锁:setnx(key,threadId)
- 设置超时时间:expire(key,60)
- 解锁:del(key)
53. 消息队列的使用场景有哪些?
- 秒杀活动,削峰填谷(双十一),延迟业务处理。
- 模块解耦,把两个模块独立,比如支付完成后,给用户返积分,这个时候不用在支付模块里添加新增积分的功能,只需要把新增积分的接口添加到支付确认的消息队列即可,后面再添加任何功能只需要订阅对应的消息队列即可。
54. 消息队列包含哪些核心角色?
- 生产者(producer):负责产生消息;
- 消费者(Consumer):负责消费消息;
- 消息代理(Message Broker):负责存储消息和转发消息。
55. JMS 和消息队列的关系?
JMS(Java Messaging Service)是 Java 平台上有关面向消息中间件的技术规范,通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,翻译为 Java 消息服务。它是 Java EE 中定义的一组标准 API,它自身并不是一个消息服务系统。
56. ActiveMQ 的基本使用?
Linux 下安装 ActiveMQ:下载 activemq 压缩包(apache-activemq-5.13.0-bin.tar.gz)解压,执行 apache-activemq-5.13.0/bin/activemq,检测 activemq 是否安装成功:netstat -an | grep 61616
。
ActiveMQ 前端控制台端口默认 8161 端口,在 jetty.xml 中的 jettyPort 对应的 port 可以改成你想要设置的端口。部署完毕后可以打开 http://localhost:8161/admin/ 进入控制台页面,账号密码默认 admin。
在 conf/activemq.xml 中 61616 的默认端口来自 transportConnector 对应的 URI 地址,如果想要修改或新增端口,也可以在这个地方新增或修改。
ActiveMQ 启动命令为 activemq start,停止命令为 activemq stop
,查看运行状态命令为 activemq status
。
57. ActiveMQ 消息传输模式
点对点模式
在点对点模型中,一个消费者对应一个生产者,生产者将消息放入队列中,当消费者请求队列中的消息时,消息会从队列中取出,并投递给消费者,消息投递后会从队列中删除,这样就可以保证消息只能投递给一个接收者。而且消息发送客户端与接收客户端没有时间上的依赖,发送客户端可以在任何时刻发送信息到队列,而不需要知道接收客户端是不是在运行。
发布/订阅模式
一个生产者产生消息发送后,可以被多个消费者进行接收。消息会发送给一个主题,与队列类似,多个接收者都可以监听一个主题。但与队列不同的是,消息主题的所有订阅者都会接收到此消息。并且必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态。
58. ActiveMQ 的消息持久化策略
消息持久性对于可靠消息传递来说是一种比较好的方法,即时发送者和接受者不是同时在线或者消息中心在发送者发送消息后宕机了,在消息中心重启后仍然可以将消息发送出去。消息持久性的原理很简单,就是在发送消息出去后,消息中心首先将消息存储在本地文件、内存或者远程数据库,然后把消息发送给接受者,发送成功后再把消息从存储中删除,失败则继续尝试。
ActiveMQ 的消息持久化的默认机制是 KahaDB,还有 JDBC 不过一般不用,KahaDB 可用于任何场景, 提高了性能和恢复能力。消息存储使用一个事务日志和仅仅用一个索引文件来存储它所有的地址。KahaDB 是一个专门针对消息持久化的解决方案, 它对典型的消息使用模式进行了优化。在 Kaha 中,数据被追加到 data logs 中。当不再需要 log 文件中的数据的时候, log 文件会被丢弃。
配置方式:在 conf/activemq.xml 文件中
六、MySQL
59. 数据库的三范式是什么?
- 第一范式:强调的是
列的原子性
,即列不能够再分成其他几列; - 第二范式:一是表必须有一个主键;二是没有包含在主键中的列必须完全依 赖于主键,而不能只依赖于主键的一部分;
- 第三范式:任何非主属性不依赖于其它非主属性。
60. ACID 分别指的是什么?
- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
- 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。
61. SQL 的内连接、左连接、右连接有什么区别?
内连接是把匹配的关联字段显示出来;左连接会读取左边数据表的全部数据,即使右边数据表没有对应数据。右连接会读取右边数据表的全部数据,即使左边数据表没有对应数据。
62. MySQL 索引是怎么实现的?
MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是一种数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。目前主流的数据库引擎的索引都是 B+ 树实现的,索引的性能也是更好的。
63. 怎么验证 MySQL 的索引是否满足需求?
需要根据查询需求来判断配置哪种索引,确定索引后,可以通过 explain 命令来查看执行计划,确认是否满足需求。explain 语法:explain select * from table
。
64. 说一下数据库的乐观锁和悲观锁?
- 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。
- 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
65. MySQL 问题排查都有哪些手段?
- 使用 show PROCESSLIST 命令查看当前连接信息,通过 MySQL 的端口定位是哪个线程占用(
netstat -ntp |grep 46888
),通过线程号排查是哪个应用(ps -ef | grep pid
); - 使用 explain 命令查询 SQL 语句执行计划;
- 开启慢查询日志,查看慢查询的 SQL。
66. 如何做 MySQL 的性能优化?
- 合理创建索引;
- 禁止使用
select *
,列出查询字段; - 定期归档数据并拆分表。
七、JVM
67. 你了解类加载过程吗?
- 类加载的过程包括了加载、验证、准备、解析、初始化五个阶段:
加载
:通过一个类的全限定名来获取其定义的二进制字节流,将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构,在堆中生成一个代表这个类的 Class 对象,作为方法区中这些数据的访问入口;验证
:主要作用就是确保被加载的类的正确性,主要包含文件格式的验证,元数据验证,字节码验证和符号引用验证;准备
:主要为类变量分配内存并设置初始值;解析
:主要是虚拟机将常量池中的符号引用转化为直接引用的过程。符号引用指的是一个标示,而直接引用是指向内存中的地址;初始化
:主要为类的静态变量赋予正确的初始值,JVM 负责对类进行初始化,主要对类变量进行初始化。
68. 什么是双亲委派模型?
当收到加载一个类的请求时,子类加载器并不会马上去加载,而是依次去请求父类加载器加载,一直往上请求到最高类加载器:启动类加载器。当启动类加载器加载不了的时候,依次往下让子类加载器进行加载。当达到最底下的时候,如果还是加载不到该类,就会出现 ClassNotFound 的异常。
69. 你熟悉 JVM 哪些垃圾回收算法?
标记—清除算法
:标记无用对象,然后进行清除回收。缺点:会带来另一个新的问题:内存碎片化。复制算法
:首先还是先标记处待回收内存和不用回收的内存,然后将不用回收的内存复制到新的内存区域,这样旧的内存区域就可以全部回收,而新的内存区域则是连续的,解决了内存碎片化的问题,但是缺点是会损失掉部分系统内存,一般是新生代使用。标记—整理算法
:首先还是“标记”,标记过后,将不用回收的内存对象压缩到内存一端,此时即可直接清除边界处的内存,一般是老年代使用。
70. 你熟悉 JVM 哪些垃圾回收器?
这里简述几个经典常用的即可:
Serial
:单线程串行垃圾回收器。ParNew
:多线程的串行垃圾回收器。Parallel
和ParNew
类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。CMS
:一种以获得最短回收停顿时间为目标的收集器,采用标记—清除算法。
71. 你熟悉 JVM 哪些调优参数?
-Xms2g
堆初始值 2G-Xmx2g
堆最大可用内存 2G-XX:NewRatio=4
新生代: 老年代内存比例 = 1:4-XX:PrintGC
触发 GC 时打印日志-XX:PrintGCDetails
触发 GC 时打印详细日志-XX:UseSerialGC
使用 Serial 串行回收器- -
XX+UseParNewGC
使用 ParNew + Serial Old 垃圾回收器组合
八、如何准备技术面试
1. 明确技术方向,匹配岗位要求
学历、工作年限、技能、项目经历、软实力。找准定位,是要做技术还是偏管理。划重点:做技术就不要提管理。面试官非常讨厌技术不扎实的人,明明是面试技术,却总是提管理。这里不是说不需要管理能力,而是要分清楚主次,只有你的技术使面试官满意了,管理能力才能为你加分。
2. 盘点个人价值,找亮点
《天道》中的一句话,博主分享给大家,不要太把自己当人,因为在 HR 们的眼中,我们都是商品,你要把自己的价值以最直观的方式体现出来,不要扯其他没用的。明确了自己有什么价值,你需要问自己一个问题:以行业标准衡量,你觉得你是哪个领域的专家?因为你只有是某个领域或者方向的专家,性价比高,HR 们才会觉得这笔买卖很划算。不要自惭形秽,你之所以平庸,是因为你没有深挖自己的亮点,在简历最后一栏自我评价里,把亮点一一列举出来,如果你实在是找不到,那总做过项目吧,能吃苦吧,善与人相处吧,逐条写出来。
划重点:项目经验多不代表能力强,要总结而不是叙述,千万不要逐个项目长篇叙述业务模块,面试官对你做过的项目业务逻辑根本不感兴趣,你需要把项目中你用过的技术列举出来,最好是只写最近的或者你最有成就感的项目,把你了解的技术栈全都写上。
3. 内推和猎头,机会大很多
选择公司也很重要,是互联网公司还是传统企业,传统企业相对重视业务,而互联网公司比较重视技术。公司主要是做什么产品、用的什么技术 。如果你的资历不够,学历双非,但技术很强,想去大厂也不是没机会。划重点:找内推、找猎头推荐要比自己投简历要机会大得多。
4. 知己知彼百战不殆
薪资、福利、平台优势、晋升机制、工作环境、人际关系、工作强度、社会地位等等,把这些全都列出来,做个表格,排好优先级。现在业界对于跳槽涨薪的幅度大都控制在 30% 以内,了解一下你的城市、这个企业这个技术方向的平均薪酬来参考。划重点:知己知彼才好跟 HR 谈薪。
5. 一份简历闯天下?不可取
不同的企业、岗位需要的技能不同,你需要制定有针对性的简历。
划重点:
- 不要随便写与岗位不匹配的技能;
- 只写项目中你负责的工作即可;
- 简历中的内容不要坑自己,每一句都要做到心中有数;
- 把项目成果最好能量化体现。
6. 练习自我介绍
直接划重点:
- 限时 3 分钟,不要太长不知所云,也不要太短显得你没准备;
- 姓名、年龄、学校、学历、工作年限,一个都不能落下,不要因为学校或者学历一般而不介绍,躲不过去的不如坦然面对;
- 两三句话概括你做过的项目,千万不要摊开了讲,否则你下面就不要说了,面试官一般会直接打断你,进入问答环节;
- 以总述的方式来讲你所擅长的技术,注意只谈技术别扯其他,诸如管理能力、组织能力、兴趣爱好等等千万别扯。
最后,拿得出手的经典项目准备一个,刷刷面试题,还要准备一些非技术类问题,比如这个必问的经典问题:你为什么离职?关于这个问题,说心里话,没必要那么固执。不要回答“上个公司加班太多,工作生活不能兼顾诸如此类 “,这样回答虽然没毛病,但是却不是标准答案,试问哪个互联网公司不加班?如果有,谁不想去?这个问题标准答案是:我的个人职业规划的原因,我需要一个更大的平台来施展,不断地见识、学习和成长。
最后还要准备一两个问面试官的问题,标准答案:贵公司当前使用的主流技术栈有哪些?如果我顺利通过面试,我将会加入哪个团队?我未来的工作方向是什么?千万别扯别的,诸如你们公司薪酬大概是多少?(保密的不知道吗),你们加班多不多?(废话)。管住好奇心,这些问题等你过了技术面试,留着 HR 来回答你。
大家看看,面试前都要准备那么多,如果是资深工程师岗位或者技术专家岗位,你可能起码要准备 3 个月,即便是初/中级工程师,面试前也要认真准备 1 个月,这样你的面试成功率才会高很多。
写了很多,大家发现我很爱说“划重点”、“标准答案”、“千万别扯” 之类,因为真的就是这样。仿佛回到高三时,语文老师教我答题,他的口头禅是:不要乱写、不要你以为、按标准答案去“套”。非常感谢我当时的语文老师(语文没有拖我的后腿,偷笑),以理科状元的优异成绩考入华科。所以,我认为求职并不是一场对等的谈判,而是一场考试(当然如果你是 BAT 系的大神,另当别论,这里不纠结哈),高考有考霸,那么面试呢自然也会有面霸,都有套路,这取决于你对套路的掌握程度。
其实还有很多话,担心思路一旦打开,喷涌而出,刹不住车了(大多也是在倒苦水,面试官也很无奈,哈哈,把面试者在面试过程中的不按套路出牌的地方梳理总结一下,给后来的人以指引,不至于掉坑)。