(先来个笑话轻松一下)
亲爱的程序员求职者们,相信你们一定深有体会,求职面试这条路有多难走。
首先,让我们来看看这个卷得让你喘不上气来的Java领域。
Java基础知识,多线程,并发编程,集合原理,JVM原理……啊!别跟我提这些!面试官一下子拿着这些知识点就冲你扔过来,还有那魔幻的Java框架,你要是不懂Spring全家桶、Dubbo、Netty、MyBatis等,就别想踏进这个行业的大门。
没错,Java领域可是卷得一塌糊涂啊。
程序员在找工作时,经常会出现这样的困惑。
1)“面试造火箭,工作拧螺丝”,为什么会出现这样的问题?为何其他行业好像没有出现这样的问题?
2)面试为什么总是被问底层原理和算法。
3)面试的时候与面试官沟通得很好,但最后没给我发Offer,这是为什么?
下面先来帮助大家了解程序员这个行业找工作的“潜规则”。
关于“面试造火箭,工作拧螺丝”,很多求职者认为这个现象不太合理,“我做了这么多年开发,虽然不太懂原理,但是你让我去写代码肯定没问题啊!你问的这些原理,我工作中又用不到,怎么可能回答得上来?而且,你招人进去最后还是做业务开发啊!”这是很多程序员的内心独白。对于这个问题我们从两个方面来说。
1)国内程序员的现状。下图是从Mob研究院的调研报告里面获得的。
从图中可以看到,国内程序员人数几乎每年都在增长,到2020年,国内程序员人数突破了250万。中国软件行业协会教育与培训委员会在2021年3月出的一份“2020年度软件和信息服务技术人才供需现状研究报告”也验证了这个数据的真实性。在这份报告中估算了2020年国内程序员总人数大概在280万,虽然这两组数据有30万的差额,但是也从侧面说明了国内程序员人数基本上在这个量级。2020年中国程序员各类工程师占比如下图所示。
程序员人数的逐年增长,带来的其实就是行业的竞争压力更大。对于企业来说,选择会更多。要知道,企业招聘的名额是有限的,当一个企业发布一个岗位需求,但是收到了上百份简历时,企业就有了选择的权利,对于学历、背景、项目经历、工作年限都会提出很多要求,甚至薪资还会压得比较厉害。即便是这样,你也得认,因为对你来说,选择权不在你,而是在公司。但是,如果反过来,企业招聘需求很大,但是来面试的人很少,这个时候,公司就会降低要求,学历、背景等通通不重要,只要你能做开发就行。但现状是,程序员人数每年都在增加,再加上市场行情的变化,实际上是一种供过于求的状态!
2)企业面临的人才筛选困难。在Java这个领域,没有一个能够被大家认可的评级标准。不像学历教育,你是985、211出来的,就能证明你很优秀,但是软件开发却没有这种标准。企业在做人才选拔的时候,也很头痛。企业除了通过你的简历和你的项目经验去了解你,以及在沟通中去了解你用过的技术,没有其他方法对你进行深度测评。另外,Java技术生态发展了20多年,已经非常成熟了。任何一个0基础的人,只需要通过3个月的培训,就能上岗写代码,完成基本的业务逻辑开发。大部分业务程序员只需要掌握几个基础框架,就能够应对90%的问题。这种现象导致了两个问题:
因为在工作中对技术能力要求不高,所以开发人员过多地关注业务,导致技术的沉淀非常少。
对企业来说人员的可替换性更高了,工作3年和工作6年,除业务上更加熟练外,在技术上的差异并不大,再加上技术生态足够成熟所以工作3年也能够完成公司的开发任务,因此企业可以选择成本更低、更年轻的人。
基于上述种种,导致企业在面试的时候,如果只关注你做的项目和技术的使用,是无法区分你和其他求职者之间的差别的。因此只能在面试的时候不断地试探你的技术底线,从各个方面去寻找一些能够让面试官录用你的理由。这里有一个非常简单的常识:“造火箭的人可以随时去拧螺丝,但是拧螺丝的人能去造火箭吗?”一个对技术底层原理掌握得好的人,在实际开发中,编码能力和解决问题的能力一定要比那些不懂技术底层原理的人更强。
很多一二线的互联网公司,他们对于招聘岗位的要求很高,但同时会给到这个要求匹配的薪资。
两个同样工作年限和工作背景的人,一个要2万元,一个要3万元,如果要3万元的那个人确实很优秀,那么有些公司宁可给出3万元去招这个人。
所以,从这方面来说,企业为了更好地去识别“优秀人才”,除了了解你的工作背景和项目经历,还会从各种技术底层的实现原理,以及算法等问题去进行考核。
古人云: 求其上者得其中,求其中者得其下,求其下者无所得。虽然对于求职者来说,非常不友好,明明是进去写业务代码的,但是面试的时候各种“刁难”。但对于企业来说,这确实是一个非常有效的筛选手段。
另外,随着公司业务规模的扩大,一旦接到新的需求,如果确定要做,那行动必须要快,临时招人太慢了。所以只能安排现有团队的人员来做,这个时候,造火箭的能力就有了用武之地。如果没有这个能力,导致项目交付延期,最终带来的损失反而更大。
有些小伙伴明明感觉自己面试表现得很好,但是却没有收到Offer。有些人在面试中表现得很一般,却收到了Offer,搞不清楚为什么?
首先要明白的是,好的公司的招聘岗位竞争是非常激烈的。笔者以前招人的时候,就一个Java高级开发岗位,招聘旺季的时候每天大概会收到70多份简历。经过HR筛选完以后,到笔者这边的简历大概会有30份左右,笔者这边再做一次筛选后,会让HR约过来面试。大家想想,这么多人来竞争一个岗位,你是最优秀的吗?如果你很优秀,那你的性价比是最高的吗?所以,在面试过程中表现不错,但没有收到Offer,无非有以下几个原因。
1)你太贵了。
2)在求职者里面有比你更优秀的人。
3)因为公司内部调整,这个招聘名额“被锁了”。
反过来说,如果你面试表现一般,但是你被录取了,也很简单:
1)你的性价比是求职者里面最高的。
2)综合对比下来,你可能是所有求职者里面表现相对较好的。
3)你在面试的时候有些问题回答得还不错,面试官正好看中了这些点。
没错,这个行业卷啊,但是烦恼转瞬即逝,只因现在有了一本强大的新书空降,在这炽热的夏日带来一股清凉的Java知识。这本名叫《Java面试八股文:高频面试题与求职攻略一本通》的书,简直是Java求职者的救星。
如果你还在为Java面试而苦恼,那这本书完美地囊括了Java面试的方方面面近200道高频面试题,从Java基础知识、并发编程、集合原理,到JVM原理、I/O与网络编程,再到设计模式、分布式与微服务,MySQL数据库、缓存与NoSQL,消息中间件……应有尽有,想不掌握都难!
更令人兴奋的是,这本书不仅有理论知识,还提供了大量实战场景与面试简历实操技巧。近20个经典高频实战场景解决方案,从服务器反应慢到秒杀设计,从架构设计到常见解决方案,无一不是伤害求职者心脏的“锋芒之剑”。同时,更有10多个面试简历实操技巧,包括简历编写与投递技巧、面试谈薪技巧、求职决策技巧等,一次性解决你的求职难题!
话虽如此,读者朋友们可能会问,要是我读这本书还不能解决我的痛点怎么办?放心,这本书每道题都标注了难度指数、考查频率、开发年限和匹配岗位,而且所有的面试题解都配套了视频讲解,让你在学习的过程中更加轻松愉快。相信我,这本书不仅会让你对Java面试信心倍增,更会让你在求职路上游刃有余。
你可以去翻阅一下书中详细目录:
第1篇 Java核心知识点 1
第1章 Java基础知识 2
1.1 数据类型 2
1.1.1 为什么要设计封装类,Integer和int有什么区别 2
1.1.2 为什么“1000==1000”为false,“100==100”为true 3
1.1.3 new String(“hello”)之后,到底创建了几个对象 6
1.1.4 String、StringBuffer、StringBuilder的区别是什么 8
1.2 Object对象 9
1.2.1 如何理解Java对象的创建过程 9
1.2.2 什么是深克隆和浅克隆 10
1.2.3 强引用、软引用、弱引用、虚引用有什么区别 12
1.2.4 一个空的Object对象到底占多大内存 14
1.2.5 为什么重写equals()方法就一定要重写hashCode()方法 15
1.3 其他特性 17
1.3.1 请对比一下Java和JavaScript的区别 17
1.3.2 什么是受检异常和非受检异常 18
1.3.3 fail-fast机制与fail-safe机制分别有什么作用 20
1.3.4 如何理解序列化和反序列化 21
1.3.5 什么是SPI,它有什么用 22
1.3.6 finally语句块一定会执行吗 24
1.3.7 什么是内存溢出,什么是内存泄漏 25
第2章 并发编程与多线程 27
2.1 J.U.C和锁 27
2.1.1 什么是AQS 27
2.1.2 如何理解AQS的实现原理 28
2.1.3 AQS为什么要使用双向链表 29
2.1.4 什么是CAS 31
2.1.5 什么是乐观锁,什么是悲观锁 32
2.1.6 什么条件下会产生死锁,如何避免死锁 33
2.1.7 synchronized和Lock的区别是什么 35
2.1.8 什么是可重入锁,它的作用是什么 37
2.1.9 ReentrantLock的实现原理是什么 38
2.1.10 ReentrantLock是如何实现锁的公平性和非公平性的 39
2.1.11 说说你对行锁、间隙锁、临键锁的理解 40
2.1.12 如何理解Java中令人眼花缭乱的各种并发锁 42
2.1.13 阻塞队列被异步消费,怎么保持顺序 51
2.1.14 基于数组的阻塞队列ArrayBlockingQueue的实现原理是什么 52
2.2 多线程与线程池 53
2.2.1 Thread和Runnable的区别是什么 53
2.2.2 什么是守护线程,它有什么特点 54
2.2.3 BLOCKED和WAITING两种线程状态有什么区别 55
2.2.4 为什么启动线程不能直接调用run()方法,调用两次start()方法会
有什么后果 56
2.2.5 谈谈你对Java线程5种状态流转原理的理解 58
2.2.6 谈谈你对线程池的理解 60
2.2.7 Java有哪些实现线程池的方式 62
2.2.8 线程池是如何回收线程的 63
2.2.9 线程池是如何实现线程复用的 64
2.2.10 线程池如何知道一个线程的任务已经执行完成 65
2.2.11 当任务数超过线程池的核心线程数时,如何让任务不进入队列 66
2.2.12 什么是伪共享,如何避免伪共享 67
2.2.13 wait和notify为什么要写在synchronized代码块中 69
2.2.14 wait和sleep是否会触发锁的释放及CPU资源的释放 70
2.2.15 volatile关键字有什么用,它的实现原理是什么 71
2.2.16 说说你对CompletableFuture的理解 73
2.2.17 谈谈你对ThreadLocal实现原理的理解 75
2.2.18 CountDownLatch和CyclicBarrier有什么区别 77
2.2.19 谈谈你对Happens-Before的理解 79
2.3 线程安全 81
2.3.1 谈谈你对线程安全的理解 81
2.3.2 Java保证线程安全的方式有哪些 82
2.3.3 如何安全中断一个正在运行的线程 83
2.3.4 SimpleDateFormat是线程安全的吗 84
2.3.5 并发场景中,ThreadLocal会造成内存泄漏吗 85
第3章 集合原理 89
3.1 ArrayList 89
3.1.1 ArrayList是如何实现自动扩容的 89
3.1.2 谈谈ArrayList、Vector和LinkedList的存储性能及特性 91
3.2 HashMap 92
3.2.1 单线程下的HashMap工作原理是什么 92
3.2.2 HashMap是如何解决Hash冲突的 97
3.2.3 HashMap什么时候扩容,如何自动扩容 99
3.2.4 为什么HashMap会产生死循环 101
3.2.5 HashMap和TreeMap的区别是什么 104
3.2.6 为什么ConcurrentHashMap的key不允许为null 106
3.2.7 谈谈你对ConcurrentHashMap底层实现原理的理解 108
3.2.8 ConcurrentHashMap是如何保证线程安全的 111
第4章 JVM原理 115
4.1 JVM介绍 115
4.1.1 如何理解Java虚拟机,它的结构是如何设计的 115
4.1.2 什么是双亲委派机制 119
4.2 内存管理 121
4.2.1 JVM如何判断一个对象可以被回收 121
4.2.2 谈谈你对JVM中主要GC算法的理解 123
4.2.3 JVM分代年龄为什么是15次 125
4.2.4 JVM为什么使用元空间替换永久代 126
第5章 I/O与网络编程 129
5.1 I/O基础 129
5.1.1 Java有几种文件拷贝方式,哪一种效率最高 129
5.1.2 I/O和NIO的区别是什么 130
5.1.3 谈谈你对I/O多路复用机制的理解 131
5.2 网络编程 135
5.2.1 什么是网络四元组 135
5.2.2 TCP为什么要设计3次握手 137
5.2.3 Cookie和Session有什么区别 138
第6章 设计模式 140
6.1 单例模式 140
6.1.1 在Java中实现单例模式有哪些方法 140
6.1.2 哪些情况下的单例对象可能会被破坏 143
6.1.3 在DCL单例写法中,为什么主要做两次检查 147
6.1.4 哪些场景不适合使用单例模式 150
6.2 代理模式 151
6.2.1 什么是代理,为什么要用动态代理 151
6.2.2 JDK动态代理为什么只能代理有接口的类 153
6.3 责任链模式 155
第2篇 框架源码与原理 159
第7章 Spring全家桶 160
7.1 Spring框架 160
7.1.1 为什么要使用Spring框架 160
7.1.2 Spring IoC的工作流程是怎样的 162
7.1.3 Spring中BeanFactory和FactoryBean的区别是什么 164
7.1.4 谈谈你对Spring Bean的理解 165
7.1.5 Spring Bean的定义包含哪些内容 169
7.1.6 Spring中Bean的作用域有哪些 172
7.1.7 如何叙述Spring Bean的生命周期 174
7.1.8 Spring中的Bean是线程安全的吗 178
7.1.9 Spring有几种依赖注入的方式 179
7.1.10 Spring如何解决循环依赖问题 180
7.1.11 Spring中用到了哪些设计模式 183
7.1.12 Spring中的事务传播行为有哪些 184
7.1.13 导致Spring事务失效的原因有哪些 185
7.1.14 Spring中实现异步调用的方式有哪些 187
7.1.15 谈谈你对Spring AOP原理的理解 190
7.2 Spring MVC框架 193
7.2.1 说说你对Spring MVC的理解 193
7.2.2 简述Spring MVC的核心执行流程 194
7.2.3 谈谈你对Spring MVC中9大组件的理解 197
7.2.4 Spring中@Autowired和@Resource的区别 202
7.3 Spring Boot框架 207
7.3.1 为什么越来越多的人选择Spring Boot 207
7.3.2 如何理解Spring Boot约定优于配置 210
7.3.3 Spring Boot自动装配机制的实现原理是什么 211
7.3.4 如何理解Spring Boot中的Starter 213
7.4 Spring Cloud框架 214
7.4.1 谈谈你对Spring Cloud的理解 214
7.4.2 谈谈Eureka Server数据同步原理 215
7.4.3 简述Nacos配置更新的工作流程 216
第8章 互联网常用框架 218
8.1 Dubbo框架 218
8.1.1 简述Dubbo和Spring Cloud的优缺点对比 218
8.1.2 Dubbo的服务请求失败怎么处理 220
8.1.3 Dubbo是如何动态感知服务下线的 221
8.2 Netty框架 223
8.2.1 谈谈你对Netty中Reactor模式的理解 223
8.2.2 Netty是如何实现零拷贝的 225
8.2.3 为什么Netty线程池默认大小为CPU核数的两倍 228
8.2.4 谈谈你对Netty中Pipeline工作原理的理解 229
8.3 MyBatis框架 231
8.3.1 谈谈你对MyBatis缓存机制的理解 231
8.3.2 MyBatis中#号和$号的区别是什么 233
8.3.3 MyBatis是如何进行分页的 234
第3篇 分布式与中间件 237
第9章 分布式与微服务 238
9.1 分布式通信 238
9.1.1 谈谈你对RPC框架的理解 238
9.1.2 HTTP和RPC有什么区别 240
9.2 微服务协调组件 242
9.2.1 分布式和微服务的区别是什么 242
9.2.2 谈谈你对负载均衡的理解 243
9.2.3 谈谈你对ZooKeeper的理解 248
9.2.4 简述ZooKeeper中的Watch机制的原理 250
9.2.5 ZooKeeper如何实现Leader选举 251
9.3 分布式锁 254
9.3.1 谈谈你对分布式锁的理解和实现 254
9.3.2 什么是幂等,如何解决幂等性问题 255
9.3.3 谈谈你对一致性Hash算法的理解 256
9.3.4 常用的分布式ID设计方案有哪些 260
9.3.5 实现分布式锁,ZooKeeper和Redis哪个更好 261
9.4 分布式事务 263
9.4.1 如何区分Spring中的事务和分布式事务 263
9.4.2 谈谈分布式事务的解决方案 264
9.4.3 谈谈你对Seata的理解 265
9.4.4 如何解决TCC中的悬挂问题 269
9.5 限流和鉴权 271
9.5.1 常用的限流算法有哪些 271
9.5.2 简述雪花算法的实现原理 273
9.5.3 简述Sentinel组件里的滑动窗口算法 278
9.5.4 谈谈你对OAuth的理解 279
9.6 DevOps与云原生 283
9.6.1 谈谈你对Swagger工作流程的理解 283
9.6.2 什么是云原生 286
9.6.3 什么是服务网格 287
9.6.4 谈谈你对IaaS、PaaS、SaaS的理解 290
第10章 MySQL数据库 293
10.1 存储引擎 293
10.1.1 存储MD5值应该用VARCHAR还是CHAR 293
10.1.2 能不能用MySQL的VARCHAR来存储一本小说 294
10.1.3 导致索引失效的原因有哪些 296
10.1.4 什么是聚集索引和非聚集索引 297
10.1.5 谈谈你对B树和B+树的理解 298
10.1.6 为什么MySQL的索引结构要采用B+树 302
10.1.7 MySQL索引的优点和缺点是什么 303
10.1.8 为什么SQL语句命中索引比不命中索引要快 304
10.1.9 MySQL中MyISAM和InnoDB引擎有什么区别 306
10.1.10 MySQL表设计时间列用datetime还是timstamp 309
10.2 事务 310
10.2.1 如何理解 MySQL的事务隔离级别 310
10.2.2 MySQL事务的实现原理 312
10.2.3 谈谈你对MVCC的理解 314
10.2.4 MySQL的InnoDB如何解决幻读 315
10.3 性能优化 318
10.3.1 执行SQL响应比较慢,你有哪些排查思路 318
10.3.2 数据库连接池有什么用,它有哪些关键参数 321
10.3.3 为什么分布式系统中不推荐使用多表关联查询 322
第11章 缓存与NoSQL 324
11.1 Redis缓存 324
11.1.1 谈谈你对Redis的理解 324
11.1.2 如何解决缓存雪崩、缓存穿透和缓存击穿问题 325
11.1.3 简述Redis持久化机制RDB和AOF实现原理 328
11.1.4 简述Redis中AOF重写的过程 330
11.1.5 Redis的内存淘汰算法和原理是什么 331
11.1.6 谈谈你对时间轮的理解 333
11.1.7 Redis到底是单线程还是多线程 334
11.1.8 Redis存在线程安全问题吗 336
11.1.9 Redis和MySQL如何保证数据一致性 337
11.2 其他NoSQL 340
11.2.1 谈谈你对NoSQL的理解 340
11.2.2 对比FastDFS说明MinIO的优缺点 342
11.2.3 谈谈你对Elasticsearch的理解 344
第12章 消息中间件 347
12.1 RabbitMQ 347
12.1.1 谈谈你对MQ(消息队列)的理解 347
12.1.2 谈谈你对RabbitMQ工作原理的理解 350
12.1.3 RabbitMQ是如何实现消息路由的 351
12.1.4 RabbitMQ如何保证线上MQ消息不丢失 353
12.1.5 RabbitMQ如何实现高可用 356
12.2 Kafka 358
12.2.1 Kafka为什么这么快 358
12.2.2 谈谈你对Kafka零拷贝原理的理解 360
12.2.3 Kafka如何保证消息不丢失 362
12.2.4 Kafka是怎么避免重复消费的 364
12.2.5 Kafka如何保证消息顺序消费 366
12.2.6 谈谈你对Kafka数据存储原理的理解 368
12.2.7 什么是ISR,为什么要引入ISR 370
12.2.8 Kafka副本是如何完成Leader选举的 371
12.3 其他中间件 373
12.3.1 RocketMQ为什么要放弃ZooKeeper 373
12.3.2 谈谈你对RocketMQ分布式事务原理的理解 375
12.3.3 谈谈你对Pulsar的理解 377
第4篇 经典场景与求职攻略 383
第13章 互联网经典场景 384
13.1 服务器反应慢 384
13.1.1 线上服务器CPU飙升,如何定位到Java代码 384
13.1.2 生产环境服务器变慢,如何诊断处理 386
13.1.3 线上接口负载剧增,快扛不住了,你的首选方案是什么 388
13.2 秒杀设计 388
13.2.1 从全局角度如何设计一个秒杀系统 388
13.2.2 如何解决秒杀系统中超卖、少卖等问题 391
13.2.3 如何设计百万并发场景中的抢优惠券业务 392
13.2.4 如何设计春节抢红包金额随机的算法 394
13.2.5 如何设计订单超时自动取消功能 396
13.3 架构设计 397
13.3.1 Java Web开发如何解决跨域问题 397
13.3.2 如何避免订单重复提交和支付 401
13.3.3 日数据量超300万条的监测系统,该如何设计数据库架构 403
13.3.4 手机扫码登录到底是怎么实现的 405
13.3.5 线上单表数据量达到1亿,如何做分表迁移 406
13.3.6 如何统计亿级用户的在线状态 408
13.3.7 线上MySQL数据库连接池泄漏,该如何排查 410
13.3.8 短信验证码接口被狂刷,怎么办 413
13.3.9 简述互联网架构20年来的演变过程 414
第14章 面试求职攻略 420
14.1 简历编写与投递技巧 420
14.1.1 找工作与从一份精美的简历开始 420
14.1.2 如何有效并且精准地投递简历 431
14.1.3 简历投递和职业发展的关系 433
14.1.4 什么时间投递简历最有效果 434
14.2 面试谈薪技巧 437
14.2.1 了解行业面试潜规则 437
14.2.2 打有准备的仗更容易获得胜利 440
14.2.3 面试过程中如何更好地展现自己 444
14.2.4 巧妙回答面试中的常见问题 448
14.2.5 捕捉面试官的微表情并做出及时反应 450
14.2.6 HR问薪资的时候,应该说多少 452
14.3 求职决策技巧 455
14.3.1 拿到多个Offer时应该如何选择 455
14.3.2 到底要不要去外包公司 458
14.3.3 如何和现在的公司友好地说分手 460
附录A 互联网程序员职业成长发展路线图 463
附录B 互联网程序员职业各成长阶段能力模型图 464
附录C Java互联网程序员技术成长路径 465
如果这本书对你的胃口,那么赶紧行动起来吧!
相信这本书可以成为你职业生涯中的有力助推器,事半功倍、轻松捞到心仪的Java工作。别犹豫了,已经给各位粉丝老爷申请到了最优惠的价格,冲冲冲,最后祝愿大家都能拿到自己心仪的Offer!
Spring Cloud是一系列框架的有序集合。利用Spring Boot的开发模式简化了分布式系统基础设施的开发,如服务发现、注册、配置中心、消息总线、负载均衡、断路器、数据监控等(这里只简单的列了一部分),都可以用Spring Bo...
本篇我们根据架构图进行代码的构建。根据微服务化设计思想,结合spring cloud本身的服务发现、治理、配置化管理、分布式等项目优秀解决方案,我们使用Maven技术将框架进行模块化、服务化、原子化封装,也为后期的热插拔、持续集成做一些...
上一篇我们介绍了spring cloud云服务架构 - particle云架构代码结构,简单的按照几个大的部分去构建代码模块,让我们来回顾一下: 第一部分: 针对于普通服务的基础框架封装(entity、dao、service、co...
读者评论