- 熟练掌握Java语法、集合等基础框架。
- 熟练使用MySQL数据库。[事务、索引和SQL语句调优]
- 熟练掌握多线程基础知识。[并发理论、关键字、锁、线程池和其他并发工具]
- 熟练掌握JVM原理。[运行时内存区域、类加载、对象创建过程和内存布局、内存分配与垃圾回收]
- 熟练掌握Spring、SpringMVC、SpringBoot等开源框架。[IOC、AOP、SpringBoot自动装配原理]
- 熟练掌握Dubbo、Zookeeper开源分布式服务框架。[Dubbo服务暴露、引用和调用过程的基本原理]
- 熟练掌握常用的设计模式,熟练使用Maven项目构建工具,构建聚合工程。
- 熟练使用Linux常用命令,掌握Nginx的适用方法及负载均衡侧脸
- 掌握基本的数据结构和算法,了解基本的计算机网络协议,如Http、TCP和UDP等。
面试官你好,我是xx,xx硕士,今年xx岁,到目前为止,在一家公司有着两年的Java后端的开发经验,在公司参与过两个比较大型的项目,并且在此期间的话就是熟练掌握掌握了java基础,还有mysql,一些像多线程 JVM,还有一些springboot全家桶之类的一些基础知识还有一些主流框架。并且呢在这个项目中,也锻炼了我使用常见的设计模式,并且呢还对于linux服务器也管理过一段时间,嗯在这个期间呢还是得到了很多的锻炼,里面还有很多的一个心得体会。 嗯关于我离职的原因的话,就是虽然目前公司他的体制很大,就是大概有2000多的员工,但是呢因为公司它毕竟不是一个互联网公司,它的数字化格局比较小,啊所以说很多平台都是那个公司自己内部使用,我想去一个互联网背景公司或者是大一点的公司来开阔视野,提升自己的能力。面试官这些。
嗯好的好的。因为你之前跟我聊过,就是可能项目上的东西比较敏感嘛,我们就更多的就是聊基础相关的好吧?唉嗯好的,刚刚我听你说过啊,你就是你简历上有写嘛,就是熟练的掌握Java的语法和集合等基础框架嘛。
嗯嗯嗯啊,集合的话你平时用得比较多的有哪些?啊集合的话像collection下的一个类似的集合,有ArrayList,还有linkedlist例子的。然后嗯另外一个像是那个set集合的话,是有些是hashset,然后另外一个是嗯这个啊那个map框架里面是有一个用的是hashmap,然后还有一些可能涉及到线程安全的话,可能会用到他的一个concurrenthashmap,现在那我们我们先聊一下那个嗯ArrayList和linkedlist吧,你分别跟我说一下他们两个就是做了什么样的一个场景,或者在什么样的场景下会去考虑到用它呢?啊首先嗯ArrayList他是底层它是一个数组,然后它的那个初始化的时候,她的数据量是0,然后当你add的时候,他会变成10,然后他的扩容呢其实是,他之前的1.5倍,然后他的特性呢就是他的那个呃嗯 查询还是比较快的,但是他的那个嗯删除,那个效率是比较低的。另外呢就是嗯像linkedlist他的一个底层结合就是一个带有头节点和尾节点的一个双向链表,然后他提供的是两种插入方式,一个是一个头插,就是那个呃linkd first,还有一个尾插是linklast,然后呢它的特性呢就是非常适合于一些呃经常的就是经常的一些增加,然后还有它的一个厄删除,但是他的一个查询有时候式如果你的量特别大,他是比较man。 他你说是linklist是吧?对,那他为什么慢呢?嗯他事比如说你要查询因为他是一个链表,他查询的时候他会嗯如果你要是查询个哪一个,然后他会一个一个比较,他会从第一个开始比。嗯然后那arraylist它查询的时候就会很快嘛,嗯查询他事它是根据那个嗯角标去查的,所以他很快。那它们两个在遇到线程安全的一些情况下,但是你又想使用List你会怎么用? 这有一个解决方法,使用一个老土的Vector,它跟,ArrayList-样底层都是一个数组,它与ArrayList有一点区别是,它其中大部分的方法都被synchronized关键字所修饰,所以说它是一个线程安全的。它扩容的时候与 ArrayList还有点区别它的扩容是以2倍扩容 刚你还提到了Map包下面的像 HashMap 我们就常规的来聊一下 HashMap 把你知道关于 HashMap的一切 你跟我说一下吧 首先,从它的底层结构来说 它的底层结构在1.7和18版有点不一样 它在17版的时候 它的底层数据结构是一个数组加上一个单链表 然后到18版的时候 它就改成数组加上单链表 或者说是红黑树的方式 当单链表和红黑树之间的转换 它的单链表的长度大于等于八 并且它的hash桶大于等于64时候 它会将单链表转换成红黑树形式存储 它在红黑树的节点的数量 如果要是小于等于6的时候 它会重新再转成一个单链表 这是它底层结构的一个变化 另外一点关于它Hash桶的数量 它的数量默认是16个,它的阈值默认是0.75 还关系到它的扩容 稍等一下,刚刚你提到它的扩容 它具体是怎么扩容的? 扩容时候它是首先会检测数组里元素个数 因为有 rload Factor的默认值为075 它含有的桶数默认是16 它的阈值是16*0.75=12 当它哈希桶占用的容量大于12的时候 它就会触发扩容 它会扩容成之前哈希桶容量的二倍 它会同乘2的N次幂 会把之前那些元素再次进行一次哈希运算 然后添加到新的哈希桶里面 是按照链表或者红黑树的方式再排列起来 它是这样的一个扩容机制 你跟我说一下它是不是线程安全的 在插入操作的时候多线程会有数据覆盖的可能 另外它在17版本的时候 这里有个线程不安全的原因是 它在PUT的时候还有个 Resize的过程 这个过程会造成它的头插 因为它17版的头插 会形成一个环形链表导致一直死循环 它的1.8版本改成尾插了 那正常是如何替代它的呢? 比如说我们如何保证它的线程安全呢? 比如给它加锁 或者你平时开发的时候是怎么保证的? 会使用 ConcurrenthashMap替代来保证它的线程安全 还有 Hash Table或 Collection. Synchronized来替代 为什么选择了 ConcurrentHashMap? 这点倒是没考虑 我是通俗意义上觉得它更常用一些 你没有做过对比 比如说机子的性能 或者说它们之间的一些差距的 这个没有做过对比 那你跟我聊下 ConcurrenthashMap 首先它的数据结构在17版底层是个分片数组 为了保证线程安全它有个 Segment锁 这个 Segment继承于 ReentrantLock 来保证它的线程安全的 它每次只给一段加速来保证它的并发度 另外在1.8的时候 它改成了与 HashMap一样的数据结构 数组加单链表或者红黑树的数据结构 在18版它会逐渐放弃这种分片锁机制 而使用 Synchronized和CAS来操作 因为在1.6版的时候VM对 Synchronized的优化非常大 现在也是用这种方法保证它的线程安全 刚刚你提到1.7版之前 Segemt分段锁 那你知道它如果要找到具体的值 它会经过几次哈希吗? 或者它是如何去找到一个具体数值的? 抱歉,这个我没有看过 那你后面可以去了解一下 刚说18版之后它是CAs加 Synchronized 那你说下CAS是什么? CAS相当于一个轻量级的加锁的过程 比如说你要修改一个 但在并发量不是特别大的情况下 锁竞争不激烈 你要修改个东西 你要先查,查完之后 再修改 修改完 准备写之前 它会再查一次,比较之前的结果有没有区别 若有区别说明这个修改是不安全的 如果没有区别 这个修改是安全的 这时它可以安全的去修改 而不是直接加锁的那种形式 在低并发的情况性能会好一点的 理解它的时候比较容易么 见名知意 CAS, Compare And Swap 比较并替换 那它有什么优缺点? 刚刚你说过它的有点比较轻量级 那在高并发情况下大量使用它 它有缺点呢? 首先当并发量特别大的时候 它始终有个忙循环的过程 对CPU的性能消耗还是比较大的 当高并发的时候建议直接使用状态机,锁之类的 另外它可能会产生一个ABA的问题 之前读和再过段时间读中间会被第三人修改过 但是它又给改回来了 这个问题可以通过添加一个戳或标志位来解决 这个问题可以通过添加一个戳或标志位来解决 保证它中间没有被篡改过 就是相当于加版本号、标志之类的,对吧 刚你提到了 Synchronized,再跟我聊下它 关于 Synchronized的使用方式 可以用在比如说同步代码块 还有它同步代码块时是可以指定任意的锁 对象作为琐 当它在应用于方法上的时候 它的锁定就是锁this 如果是用静态方法则锁定是它的cass对象 关于 synchronized在JKD1.6时候升级还是蛮大的 首先它提供 因为它的锁是一个种类 因为它的偏向锁 是它的轻量级锁 最后到重量级锁 一般在偏向锁的情况下 它就偏向于获得第一个锁的线程 它会将线程拉到这个锁对象的对象头当中 等其它线程来的时候 进而跑到一个轻量级锁 轻量级锁也是在低并发情况下 来消除锁的源于 它主要是在虚拟栈中开辟一个空间 叫 Lock Record 将锁对象的 Mark Word写入 再将尝试将另一 Lock Record的指针 使用CAS去修改锁对象头的那个区域 使用CAS去修改锁对象头的那个区域 使用CAS去修改锁对象头的那个区域 它也是普遍应用于一个低并发的情况 它也是普遍应用于一个低并发的情况 在往上如果锁定竞争非常激烈 那就会立刻膨胀为一个重量级锁 那用的是一个互斥锁的过程 像它的加锁过程 锁它的主要实现原理是 我先说下同步代码块会比较好 在它编译之后 会在你的代码块前后加上两个指令 一个是 mointerenter 另外一个是 mointerexit 个线程来时 它发现这个对象图中 它的锁标志位是无锁 应该是01的状态 它会尝试给一个互斥锁对象 锁对象的时候会跟另外一个对象关联,就是监视器锁 monitor 它会在 monitor的一个锁定器加1 并且将 monitor的指针写入到一个对象头中表示 并且修改它的锁对象标志位为10,就是它重量级锁的一个标志位 那以此完成换锁的过程 并且它的这个过程是可重入的 因为它不会每次出去 需要再加锁还要再释放锁 它每次进来后获取这个锁,让锁记录加1即可 它加锁完之后 当其它线程来的时候 它会检查到这个锁对象头中 monitor.监视器锁上计数器不为O 它会在 monitor监视状态下等待去竞争这个锁 如果之前的结束了操作 它就退出开始释放这锁 并且逐步的将加上的锁定释放几次 将计数器清零来完成对锁的一个释放 让其它线程继续去竞争这个锁 这是它重量级锁同步代码块的一个原理 接下来说下同步方法吧 它不是这种指令而是一个 ACC SYNCHRONIZED标记位 相当于一个fag 当JM检测到这样一个flag 它自动去走了一个同步方法调用的策略 这个原理是比较简单的 何时用它、何时用 ReentrantLock有考虑过么? 嗯,有 它们俩对比的话区别还是蛮大的 从JM层面上 Synchronized是JVM的一个关键字 Reentrantlock其实是一个类 你需要手动去编码 像 Synchronized使用时候是比较简单的 我直接通过代码块或者直接同步方法 我也不需要关心锁的释放 但 Reentrantlock 我需要手动去Lock 然后配合 try finally代码块一定要去把它的锁给释放 另外 Reentrantlock相比 Synchronized有几个高级特性 它提供了一个 如果有一个线程长期等待不到一个锁的时候 为了防止死锁 你可以手动的去调用一个 locklnterruptibly方法 尝试让它去释放这个锁 释放自己的资源不去等待 Reentrantlock它提供了一个 可以构建公平锁的方式 它的构造函数有一个但是不推荐使用 它会让 Reentrantlock等级下降 此外它提供了一个 condition 你可以指定去唤醒绑定到 condition身上的线程 来实现选择性通知的一个机制 这是它们之间的一个区别 关于它的选择性 把我还是推荐 如果你不需要我说 ReentrantLock以上三种特性 还是一定要使用 Synchronized 因为相比来说 Synchronized的话 它是JVM层面的关键字 当优化JDK的时候它会非常方便的去了解 当前的锁被哪些线程所持有 这些状态的话不是 Reentrantlock能相比的 还是使用 Synchronized比较好些 但是有一点我不赞同 刚刚你不是提到过 Synchronized 它锁升级的过程 那我现在给你举个例子 你可能会否定你刚刚的说法 假如我现在是滴滴或者饿了吗 我在代码里面大量的用到了 Synchronized 现在是早高峰,我叫滴滴 大家都在打车 然后我使用了 Synchronized 它锁升级 而且它的锁是不可逆的 在早上的时候所有的代码全部升级为重量级的锁了 中午或者说是平时我们打车的时候 哪怕是已经过了高峰了 但是你的锁一直是一个重量级的锁 所以在并发情况下 其实很多时候懂了吧 只是因为它不可逆 但是一旦加到重量级锁 它就始终是那个状态了 如果确保你的QPS很稳定的情况下 或者是很低的情况下 其实还是要根据你的场景去做选择的 这是一个情况 那你刚刚提到 Reentrantlock 你再跟我说一下 它里面是怎么去实现的 比如像它里面的公平锁、非公平锁 这个我没有再深入去了解了 我只知道它可以做到种程度 那像它的底层的AQS 可能你也不是很了解对吧? 这个不知道 那JUC下面你还用过哪些包 并发包下面的那些 CountDownLatch, Cyclic Barrier
CountDownLatch, CyclicBarrier 还有 Semaphore,这个几个是用过的 像 CountDownLatch适合于你单线程 在运行时 有一段过程你又希望并发的去执行 后来又回归到一个单线程状态 它适合一个线程等待一批线程达到一个同步点 之前进去就行 它的计数器是不能重用的 另外 CyclicBarrier,它是一个类似的 但它没有一个线程一个线程的等待 它是一批线程同时到达一个临界点 之后再往下走 它里面好处是 当你 CountDownLatch,它的计数器是可以留下来的 那 CountDownLatch是如何实现计数功能的 因为高并发情况下 你对数据的加减会存在并发竞争的问题 它怎么去保证的 这个我没有了解 如果你看过 ReentrantLock中的AKS 你就知道了,它里面有 state标志位 用 volatile去修饰的 volatile有看过吗 知道 那你跟我聊一下 volatile volatile是JVM提供最轻量级的一个关键字 说 volatile,首先要说到我们计算机的模型 cPU和内存之间的线程效率是差好多数量级的 但为了保证它们之间的计算 不影响CPU的计算 然后中间有好多LLV那种缓存 我们线程在这个缓存中去工作 首先它取数据会从主内存取到工作内存中 在工作内存中计算完之后再传过去 这就有一个问题,多个线程之间的可见性 是如何保证的 在计算机层面上是有好多协议 在JVM上的时候 它为了解决这些比较复杂的东西 它提供了像JMM的这种模型 像被 volatile修饰的一个变量 它就可以保证这个变量在所有线程间的可用性 在这个线程使用这个变量前 在修改这个变量之后 它可以立刻刷到主内存 它在使用时会立刻从主内存中取出来刷新那个值 volatile它是不能保证变量的原子性 像自增自减这种操作它是不能保证的 那原子性我们怎么去保证 原子性你可以使用像 Synchronized 还有 Reentrantlock通过加锁来保证原子性 还有吗 比如使用fna他也是使用了这个 并发包下面还有像 Atomic那些类吗 像 AtomicInteger 不过它底层的实现也差不多是这样 刚刚你说过 它会不断刷新到主内存里面的那个 那个是总线嗅探机制 你知道不断的去总线嗅探会有什么问题吗 好像会导致它的总线占用的资源就很大 总线风暴你到时候也可以去了解一下 我们就不做展开了吧 多线程的线程池了解吗? 了解,那你跟我说一下线程池的运行机制 线程池它是有一个核心线程数 当你的线程运行的时候 如果你没有设置成预启动加载 首发线程数为0 当你提交一个新任务的时候 它会首先是建立一个核心线程 去执行任务 如果你要是一直来任务 它之前的有没有执行完那么你会一直建核心线程 当达到最大值核心线程数时,如果还都在忙 那么就会放到 BlockingQueue里面作为节点 如果 BlockingQueue队列也放满了 而且核心线程都在忙 那就会去建立新线程 它叫做非核心线程 若一直创建数量达到非核心线程数 max access 就会触发一个拒绝策略 JDK内置了四种拒绝策略 第一种是 AbortPolicy 直接抛出异常来解决 第二种是 DiscardPolicy 悄无声息的丢弃你的这个任务 第三种的是 DiscardoldestPolicy丢奔你最早的未执行的任务 最后一种是 CallerRunsPolicy 谁调用我的这个线程去执行你的这个任务 它种方式而是会影响你的新任务提交速度 关于使用的队列,它是阻塞队列 JDK提供了两种 第一种是.忘记单词怎么读了 它是不保存任务的那种 JDK提供的 new catch线程池是使用的这种队列 第二种的话就是一个有界队列 Array Blocking Queue,你指定数量 如果要是超了 它可能会OOM的 第三种是无界队列 LinkedBlockingQueue 它可能因超出上下文而OOM的 它可能因超出上下文而OoM的 优先级队列我没怎么去用过他 关于线程池中还有一个比较重要的参数 线程构造,在创建一个线程池的时候 你要提供一个线程的 threadFactory 定要指定它名称,这是很重要的一点 你也可以设置它为守护线程 当你的BM关闭的时候 可以让线程跟着它一块消亡 像刚刚你提到的 像 Array BlockingQueue Linked Blocking Queue 这些队列的底层,你有去看过么? 它们底层好像都是我刚才不懂的AQS做的是么? 没有看过是吧? 我没有看过AQS这些就没有深入了解过 好滴好滴 看到你这提到 MySQL语句调优 索引、事务都有一定的了解 对吧?对 那你可以跟我讲一下平时的SQL调优思路么 首先呢 有条最基本的,表要有主键 因为有主键的表 My SQL会创建聚族索引 聚族索引的好处是它的主键和数据行是在一行的 你在 explain查询语句的时候会发现 它的type级别是 const,这是很高的一种级别 然后 当有主键的时候,如果一条SQL语句很慢 可以去登看是建了祖应的索引 可以去查部是建立了祖应的察引 可以去查看是香建了祖应的家引 建位索引要尽量选择 where条件后面的字段
感者是 group by 感猪者是n接的字段 民猪者局接的字段 作为你的引列 些索引列也要排个序 要符合最匹原则 符合最左匹酰原则 要符合最圆原则 你选的时候愛据们的劇引遊昪器 你选的时候要根据包们的索引选择器 你的非重复的数据布和重复的数据行中间的排紉 大的放定小的放看样的彤式 大的放左小的放右胶样的形式 沙种多列的索到列 你要去建立联合索引单个索引 是索引的选择 外 你在SQ带写的时候 你在S①L书写的时候 不要将索引列放到一个表式中 索引列放到了表达或中 感者说你用了一些反向判断 邮如 NonE不等、No种袅鍵词 NoNU不等手。No等种鍵词 此如NoN不等手、N。n等种吳鍵词 邮如NoN不等手、No等种关键词 邮如NoNu不等、Notn等种袅鍵词 它会让你的索引失效 它会迎你的索凯失效 洳如果你的数据查狗非常频磨 如果你的数据渣询非常颂 你同以考虑 给使用那种程索引 给包使用那种程家引 给窗使用那种索引 索引是可以直在索引中洵到数据的 索引是吧以在索到中塗鉤到数据的 索引是可以宜接在索引中鉤到数据的 粗网来说凝还是很快的 关于你设的索引没有生效 你也可以去考感下是不是MyQL 因为一些其的原因造成的 因为一华美它的原因造成的 二二③@的底层 有。个随机采样。会很你的索引塞数 會有。个随机踩样。啻会很据你的索引塞数 但不冋能全都給你标记上 但不吧能全都给你记上两就理父 但会很据随机踩用来算你索引数是如间的 但官会很据随机采用来锦你索到害数是如何的 但它会据随机采用来訢算你索引塞数是如间的 但它会根据机采用来讦算你家引蔧数是如问的 如果采错了 属然你的索列选择性比较大 虽然你的家引选择性较大 但含认为你的索引选择性比小 就定错索引是吧? 可以通过加oced强制宦走该索司主备显 可以通加 orce ind强制让啻走该索引王备量 回以通过加ede强制让官走该剂 可以通过加 orce inder强虽制让它走该索引 备式然后看行不行 心的需下的信息要联朋TA题 你需刷新下的信息要用 analyze TABLES 1N下的信飞 袅手数据库调优现在能想到的些 那你跟我解释下 在创建引时建唯索引还是普通索引好處 在创建索引时创建唯豪引涿瞢通索引處 在创建索引时建唯索引还是音通引好處 在创建索引时创建索引还是鲁通索点 聚族索引。是确切来说应该是种数据结构 族。确牣說应谖是一种数据结构 族家引。是确来说应该是种数据结 器族家引。是确切来说应该是。种数据结构 是特官的主链和的数据行放在的 是将的三键和官的数据放在块的 我纵识紧族索向度实数据行的有利除径 我识影族引通向度数据行的有利除途径 你受的数据可能就是索引了 族家引是我们说的普通引 的索引宿放的是吡子處和的三键 …的素引的是叶子点融色的金键 它的索引的是叶子点自的金 实它的索引存放的是叶子节点和包的宣键 在查询的时候 其实是通过已的索引列查询到它的主键 再通过主键去回表查询 还是通过一个聚族索引查的 它有一个回表的过程 速度相网来说会一處 速度相对来说会慢一点 具体还是看你的选择 比如你要是对主键进行查询的话 那么你只要建立主键 那直接聚族索引就完事了 如果那些不同字段 你想去查的话 它的查询速度可能比较慢 你需要创建一个非聚族索引来加快它的查询速度 你刚刚回答的这两个点都是OK的 只是我问的问题是唯一索引和普通索引 你可以回去看一下 因为唯一索引,它会去确保列的唯一 所以会多一次判断的过程 但它判断过程的开销是很小的 真正的开销的话是在它 buffer区的 你有时间回去看下吧 我们聊一下MvcC和事务隔离级别的关系吧 我知道事务隔离级别,但MAcC只是稍懂一点 但是我没有深入去了解过它 可以说一下事务 但这不是很应该的哦 因为事物它本身主要还是靠MvcC进行保证的 我可以说一下,但我不知道我了解的深不深 oK,那你就跟我说一下你知道的 首先 nnoDB的特性就是它支持事务 它支持事务的时候 为了保证事务的并发度,它提供了一个隔离界别 首先它有四种隔离级别 一种是 Read Uncommitted,结果什么都不能保证 它为了解决事务之间的脏读 但它对于你的不可重复读还有幻读 它都是不能保证的 下一个级别是 MySQL默认的 叫 Repeatable read 这个隔离级别可以保证不发生脏读 还有不可重复读 但它是不能保证幻读的 最后一个是 Serializab|e 它是串行化的 所有的都是串行来执行的 它是没有事务的 它是最高的安全性级别 关于解决幻读 您需要手动的去操作 因为我们知道se|ect语句 它是没有不加锁的过程 但是你可以在后面加上 当你是索引范围查询的时候 在后面加上 for update锁住你未出现的那个行 保证你的事务中不读到其它事务中的提交数据行 另外一点 for update是锁住了未出现的那行 它用的是一个行级锁 关于事务另外一个问题是丢失更新 关于丢失更新 我们会需要手动去处理一下 有两种方式 一种是乐观锁 另一个是悲观锁的形式,当乐观锁的时候 你可以使用类似于之前并发的CAS 你可以加个版本号 是先读,读完之后你再改,改的时候 往回写再读一下 跟之前的版本号进行比较 如果一致的话则安全写回 还有一种情况,你可以加个悲观锁 可以在等人查询的时候 带上一个 for update给那行上个锁 来防止丢失更新 关于事务的话,我知道就这些 正常情况你去了解事务隔离级别的时候 MvCC应该要去了解的 因为它的四种隔离级别中有两种 其实是完全靠MVcC多版本并发控制去保证的 所以应该是去了解的 我之前看过了 redo log、 undo log、 bin log 你看过了是吧 你看过了我就不问了 Spring它是怎么去做到事务隔离级别的 它是提供一个注解,叫做 Transactional 并且它提供了一个事务传播行为 我知道的有,它比 MySQL的隔离级别要多很多 但我只记住了前几个 比如说 requst 隔离级别应该只多一个默认的 你说的应该是传播特性,有七个 所以你别记错了 我又不问你 那 Spring的AOP是如何实现的? 有哪些实现方式 如果你的代理类有接口的话 那走的JK的动态代理 但如果没有的话 则使用@字偶术去创建代理类对象 则用g节偶技术去创建代理对象 则使用c岩偶技术去铡建代理类象 则使用cg定码技术去锁建代理类对象 则瘦用cg偶技术去创建代理类对象 宝要以是两个式来做的AOP 那的底层呢 =(那官的底层呢 它怎么去做代理的呢 底层。你是说JK的那个吗 你庭便兆个你熟悉的 你便兆一个你恐的 JDK中宫要是使用aN反射中的网个类 JDK中要是瘦用JaNa反射中的两个类 个PoXy 个是 nvocationHandler 色通过n的式去绑定之前的代理判不正在社 窗通时nd的方式去绑定之前的代理 窗通过bnd的或去绑定之前的代理 通过机nd的方式去绑定之前的代理 与原来的现类去做一个关系 弟国是通的来剑代理对象 弟且客是通P必祖关的来建代理对象 弟且是通过P@祖羡的来创建代理对象 弟且它是通过@关的麻创建代理对象 然后通过反射ke去执行那个方法 大致是这个程 你知道Sg个生命周期是么样的么? 行。汹个可以说下 spng的生命周期 8pdn的生命周明 我理解的是父子容器 父子容谷粗略的可以分成三个阶段 租略的吧以分成个阶 x它是有也ea的次加 一还有一个be的次加过程 还有个eam的巴次加工过程 官先m的效加工 首先。bm的第次加 事务实反原理首先n的第次加 m先的第一次加 事务实原理将你的对象独例匙 事务买现原理将你的对象实例化 在这实例化的前后 爱实例化的前局 个圆8508在局理 个召 ean postProcessor在做前置和后置处理 价 BeanpostProcessor傲前量额后量理 第二步就是的依注过程 第二步就是包的低赖详过 第二步就是的依赖外过程 第三就是它的依赖众远程 第巴涉就是窗的依赖人过程 第二步是的依赖入测程 ∞第三步就是的依赖入测程 在这个过程中 首先会设它的一个属性值 首先会设量含的三个属性值 然后包对ba实现的 BeanAware相关接回 然盾會对bean现的 BeanAware相学接回 民猪者 Diposable Bean这接回的活 就会给你的b注入相应的 aware的属性 这个阶要分抛两步 这价阶段要分为网步 啊步前也有 BeanPostProcessor处理操作 胶步前局也有BnP⊙PGS后处理操作 池内步前局也有 an PostP0ceo量处理操作 这步前局也有 Bean postprocessor后处理操作 汹网步前后也有 BeanPostProcessor后处理操作 美实这第二步做完之后实加红机制 8已经接远一个完成期了 这ben已经接远个完成期了 s但它还有价bea的次加 加值但还有个an的次加 但套有个e的已次加 “在个二欢加工前后它也是有一个 在这个三次加二前局包也是有一个 你可以像Ap回 cationconi那详 你闻以像APp道mc哪 配置、个自定义的盾理bean 醌置个自定义的后量郧理bean 配置个自定的后置处理beam 然后在过程中要是调用 你在beam中写的 airone的个为法 你在beam中写的 environment的个法 國者你的bean实现了=个 idealizing Bear 会三次回你的的tPpe道esSe法 它会二次回周你的 after Proper道eS法 对beam做进二步的设置 对bean做进一步的没置 bean的三次加工已经完成之 你的beam就经建立完成了 也就是说它会很据你bean的 scope 果要是一个单例的bean 默认是单例的 它就会走下去 如果是多实例 你的bean的 scope是 prototype 多实例的话就会移交给你去管理它后续的生命周期 当它是单实例bean的时候 生命周期还是由 Spring来管理的 当 Spring容器销毁的时候 它会调用 destory相应的方法 若你实现的是一个 Disposable Bean 实现的那个接口中也会有你销毁的逻辑 这是bean整个生命周期的过程 你回答还是比较全的 那它怎么去解决它的循环依赖的? 这个还没来得及看 但我知道它好像是一个三级缓存 对,它其实就在你生命周期中的几步 你有时间可以去看一下 就刚刚你说的 它有三级缓存这样一个概念 但它也有解决不了的那种循环依赖 后面有时间去看一下吧 我们今天由于时间问题就不做更多的展开了 JVM看过么 因为我看你简历上写了JVM 那你就跟我说一下JVM的内存模型吧 你指的是运行时段内存区域是吧 JVM运行时的内存区域可以分为两大类 一个是它线程的私有区 另外一个是线程共享区 对于线程私有 首先就是它程序计数器 这里是在JVM中栈内存比较小的一个地方 但是唯一一块不会OM的区域 这里会告诉你的执行的代码归于哪一行 上下文切换之局官吧以回到。个正确角的状态 男外线程私有的是虚以机钱和本地法栈 另外线程有的是虚现机栈和本地法栈 男外线程私有的是虚以机钱和地方法栈 男外线程私有的是虚以机钱和本地法栈暴于标记清陆大量分钾片 易外线程私有的以机钱利本地方法截 里虚机要使用的是帧 汹里机要使用的是顺 个方法的调用說是从入栈到唱钱的过 个法的调用是从外栈到出栈的过程垃级团老 。个方法的通用到幽钱的 t复OuB一个方法的周用就是从入截到性戳的脑程 (=个法的调用航是双入到的程 个动法的明围就是入钱到匙钱的程 你的程换区出 爱是你的线程美区 接着是你的线程穹区 首先要说到的是方法区一对们 完到的是方法区二 在方法区美实只是小M的个视范這 在方法区仓其突实只是J心的个规臆 但是在。版本的时候区照有代概的收以个以为带收 色的度狐Hp机中叫做永久代 窗的现在片o我以机中做永久代 它的现在 Hotspots拟机中邮做永久代 窗的段现在 Hotspo现机中邮黴永久代 它的现 Hotspo机中叫做永久代 宿放的是些常常量还有类的据信息 放的是些常量池筒有类的元竭信息 宿放的是些常量灺常量还有美的元数据信息 full go宿放的是些信量池郑有类的元数据信息 18版的时候。圆为一些原因 官转移到了一个集结内存中 它转移到了=个集结肉中的代回 转移到了个镶结内存中 它转移到了二个集结内中时有伍阳不天 它叫做元空间 液存放的是类的远数据信息 液放的是类的远数据信息认件柱行按料轴用数局样 液里的方法区也会是①M的 还有一个区短是堆 官睡存放是a闺产生的对象。象的突例 官理存放是ay产生的象。象的突例oon种卖 它闺面放是aN甲生的像象。对象的突例 m它里的存放是N哩里产生的网象。对象的例 oon种官理存放是a闺产生的象。象的突例逸分 也是GC軍点回收的个区域B逸分 分老它也是GC点回收的个区西)中的 速分弟且它也是会产生M的 客也是会产生QOM的 群最后要差的是运行常也 最后要关差的是运行常量池 它是在18时将还行常量转移到雌中 M优 JVMUNU感是在]8时特运行常量池转移到難中 UJVMWOY您是密时將行常转移中 因为之前官是在元空间里面 后来搬移到唯里面了M性测工具 N性能检测工维哩面存放的是常量沁被加载之后 M性制工1哩面存放的是常量池被加载之后 唯里面存放的是常量光波加载之局 运行时筒量沘和静忞变量都存儐到了堆中 运行时常量静态变都狩储到了堆中 运行时筒量沘和静态变量都存儐到了堆中 还何时需量和静量御到了维申 m运行时常和静态变量都狩到了中 胶是警个常量池 是警个运行常量池 手直肉的 :现在存放的是M的元空间Cpt1o05 元空间放在里的时候包有一个得处 oOM的机遇相对之前变小了很多 OK,了解 你刚多次提到OOM 你知道一个OOM的排查思路和过程么 你是说借助一些写给 jvisualvm的工具 去查询它dump下来的堆栈信息排查 说出这些也差不多 那刚刚提到了内存问题 那我们再聊一下 那它现在有哪些垃圾回收算法和垃圾回收器 你都跟我聊一下吧 垃圾回收算法有三个 第一个是标记清除 标记一些不可达的对象 比如说将判定为死亡的对象然后依次抹掉 稍等,你怎么判断那个对象是否可达呢 有两种方式,一种是引用计数 但它的缺点是可能会产生循环依赖 第二种是根据Java中 可以作为 GC Roots根节点 来开一个链 如果不在这个链上则可以判断可回收了 这可以做 GC Roots的一些亮点 比如像是虚拟机栈中引用的一些对象 像是方法区中的静态变量所引用的对象 还有常量所引用的对象 还有方法区中所引用的一些对象 我刚说错了 它可以作为可达性分析根节点的一些对象嘛 那你接着刚刚的聊吧,这种不用聊了 第一个是标记清除 它因为这种使用可能会造成很多的内存碎片 并且当它对象是比较大的时候 它的标记效率是比较低的 第二种是标记整理 先说标记复制吧 复制简单的就是粗暴的将我们的堆划分成两块 在GC的时候将一些活动对象直接复制到另一半 它的缺点它会造成你的内存支持量偏低
但它的好处是不会产生内存碎片 第三个是标记的一个整理 标记整理也是每次只使用一块区域 将一些已经死亡的对象 往另一端移动、复制然后就可以找出剩下的一块区域 主要是这三种垃圾回收算法 垃圾回收算法应该有四个 你可以回去再去看一下 应该还漏了一个 你说下垃圾回收器吧 垃圾回收器我只知道几个比较经典的 那你就说CMS和G1这两个比较经典的吧 还有一些之前比较古老的 像JDK默认使用 Serial Garbage Collector 那先说CMs吧 CMS是可以和用户线程并发操作的 GC线程与用户线程并行执行的一款垃圾回收 它的特点就是低延迟 它的整个过程的 主要是用来回收了老年代的 它的算法使用的是标记清除 可能还混合一下标记整理 因为它直接用标记清除 它会容忍一定的垃圾碎片 当达那个阈值的时候 触发一次标记整理来清理一下 它的过程有四个阶段 首先是初始标记 到并发标记 接着是重新标记 还有一个并发整理 但它在初始标记和重新标记的时候 它不是线程并行 它会短暂的产生 Stop The world 但因为这个时间是很短的 它的并发标记和并发清理 这两个阶段是耗时比较长的 但它是和用户线程一起并发执行的 所以说它可以最短的实现低延迟 你不用再聊G1了 可以说下它们两个 Stop The World的区别么? 你说cMS和G1的么?是 G1我仅限于了解到 它有很多立区域( Region) 但是太深入的就没有了解了 它是可控制的 刚不知道OOM排查过程,那你知道GC的么? 比如现在我的cPU突然飙高了 我应该怎么去排查呢 cPU突然飙高了 如果你的服务部署到Lnux上 你需要跑命令去查看下 你可以看下当前cPU百分百的进程D 然后 去登上进程来代替 OK,我了解了 知道你懂了,我就不问了 不想理我,可以 你边还对RPC框架还有自己的一些理解 那你跟我说下 dubbo服务暴露过程吧 假如说我们现在的场景都使用 dubbo协议 dubbo支持很多种协议 这个不是很清楚 好像在官网上看到过,我在它官网学的 它的 dubbo协议 还有一项rm协议,还有 thrift协议 它有很多种协议 你可以去看一下它为什么有这么多协议 按道理来说 我们正常的默认都是 dubbo协议吗 调用路默认是这个 调用日路但它有胶么多物议让你来 就证明美他协还是宥他自己的场景的 明其他也还是有他自邑的场景的 就证明美他协汉还是宥他自己的场景的 幅析标置ne你以去看下 你吧以去看下了 你接着刚刚的服务暴鑫过程继续说 买程了你着观刚的服务暴經沁程继续说C完或实了一个AMo昌aaa OC完线进实现了=个假奶你现在有个服务暴露 宽难x然后你是用Ⅻ为式来的签 吸务基国过程然局你是用式迷来的标密 务暴露过程然局你是围方式来配置的标签 然后你是用宛或来配的标箋 首先修有个dubb⊙的 DubboBean Definition Parser 首先有个 dubbo的回 uboboBean Definition Parser份中心世什器 终端解祈器了地址 终端解祈器O形青D再个保了吧址 去解祈你的标签脉国0两 像 application regist tyriam-像 application registrys建代重 o0um的些 务引用protocolo.consume的些 一会祖应的解祈成应的cQm对象 会祖应的解祈成对应的Gg对象 会祖应的解祈成对应的cOm网象具e式 具的gD代理但是有点特 置的服务不会写到对应的Ser机e标念里 但不是童接解成 Service Config 面是他S机cm下面的一个子类叫做 Service Bean 面是他 Service Config下面的个子类叫做 ServiceBean 这个 ervice Bean是很特殊的 管调因为它实现了两个接回 第一个是之前生命周期厘面的服务提供 Service Bean 到时候它会执行 after Properties Set方法 第二个比较特殊的接口是App| licationListener 因为它里面是观察者模式的 它监听的是一个 ContextRefresh Event 能够去刷新那个回调 它会等 Spring容器处理完毕后 它会回调 on ApplicationEvent的方法 但这个里面会进行两个服务的暴露 但区别是 如果它延迟暴露少就走前一个 如果它不是延迟就走 on Application Event 它里面会调用一个暴露方法 export 其实这个暴露方法在他的父类 Service Config里面比较核心的 它会多次 export 然后进入下一次循环调用 doExportUrlsFor I Protocol 然后这个fow里面有 dubbo核心SP机制 它是跟JDK还是不太一样的 它做得是更好的一层 因为他是KV的一个结构可以存储多个 它只是实例化加载某一个类就应该是所需要的服务 你的 Protocol 它会调动它的 export的一个方法 但是这 Protocol它相关的两个实现 第一个是 Registry Protoco第二个是 dubboProtocol 它在 Registry的暴露口中做的第一个 第一步就是 doLocalExport,,就是本地暴露 在这个过程中会调用 dubboProtocol里面 将里面的实现全部封装成 invoker 然后到 dubboProtoco会封装成一个 export 具体的暴露可能涉及我的知识盲区了 但我知道它开启 netty服务器 这个 expor就暴露完成了 它就会返回到 registry Protoco的暴露口中 去将之前暴露的 evoke注册到一个 registry中 并且它还会将已经暴露的 invoker 保存到它的 ProviderConsumer的注册表中 这个注册表之后会被远端引用 那个注册表的结构是什么样子的 它是一个 Concurrenthash Map 它的key是 string,它的vaue是set 第一个写了两个 一个是 provider一个是 consumer这个两个 那些像N|O、B|O你了解吗 不了解了 它们底层跟这些比较相关 那它用的注册中心zK zK你了解吗 你只知道它的一些特性和初始的选举 还有它的监听 那我就不问你了 你这边简历写了常见Lnux命令 刚刚问过你了 还有 Nginx的使用方法以及负载均衡策略 Nginκ有哪些负载均衡策略 首先是连询 还有一致性哈希还有加权的那种 就这三种吧 你自信 一致性哈希的时候它是怎么做的? 相同请求参数的情况都会打到同一台机器上 你还知道Ngnx的其他什么 像压缩这种 还有写一些虚拟主机的配置 还有像负载均衡一些配置 就这些了 说两种你最熟悉的,撇开单例和工厂 最熟悉的能够在项目应用的 我将它可能会有二十个场景 但每个场景的处理方式都不一样 在这上用策略模式来做的 第二我觉得用的最多的是模板模式 还有一个是建造者模式 建造者它怎么去实现的呢 它里面有一个内部类来做的 每次都会返回那个内部类 它持有的属性与外部的属性是一致的 然后每次的返回都是内部类 就可以直接链接调用 最后使用 tosting把里面的 然后把它拼成一句话让它做 这些都问的差不多了 再加上项目的话 你的项目敏感,我就不问了好吧 你之前在北大读研究生 在你的研究生期间 你觉得不错的项目是什么 研究生期间你就最得意的项目吧 什么方面都可以,不一定是技术方面的 你就可以说你项目上的一些收获 研究生期间跟老师做的是跟深度学习相关的东西 也有模型这种像图像识别 之前做过实验室场景和物体的场景 还有人脸那种识别的操作 那相当于是你研究生期间还是以算法为主了 对,发表那篇论文也是从那里出来的 发表的论文我看一下 一个是北大中文核心期刊 这些也是跟算法相关的 可以 那你为什么后来选择做Java呢 算法太难了么 算法比赛觉得还简单些 自己喜欢去钻研那些东西 去实现一些东西 很有成就感 而且解决问题会很有意思 你平时如何去学些新技术的 就比如除了Java之外的 我们想去了解其它新技术 你是平时怎么去学习了 肯定会有人去写一些博客 去做引导或者更潮流些会有人做些视频 我会先看博客、看视频 先上手,先了解一些关键词 了解完之后 可能会用 会用之后我就会找一些专业的书籍 它的语言是经过千锤百炼的 表达的更精确一些 去多看些书籍巩固下,了解它的底层 到时候再回过头来看,感觉会不一样 你可能更深入的去了解一些源码之类的 就这样一个思路 那你最近在看书 最近的话是看过的是JVM 最新的2019年出的那一版,我读的电子版 深入理解Java虚拟机 之前就把去年年底出第三版看了 是的 差不多了 你有想问我的吗 我想问下你们项目开发中 你们大厂里面的开发是怎样的一个模式 还是相对敏捷开发是比较常见 我们差不多都是敏捷开发为主 也有做项目管理的一些流程工具 PM就会在上面进行实时跟踪 就在指定的节点之前 完成对应的开发 然后push到指定的分支 测试、联调、灰度、上线差不多是样吧 上线之后还有一定的回归,回归的话 反正也比较久吧 还有在正式开发之前 有一个设计的过程 设计的过程其实往往会比较久一点 因为涉及到一个不确定性 这个需求讨论到最后不做了 也是有的 会去讨论需求的价值 一些细节的点确认完之后 我们没问题了 才会开始开发 差不多就样吧 那你们团队里面会经常开会么 比如像那种早会、晚会 因为我们是中间件 我们自己其实没有产品经理的 大部分都是我们 Leader 或者我们自己或者公司的同事用了我们的产品之后 我们觉得需要有改进的点 或者我们自己想去一些方向 改进这个产品 我们会去研发 所以说我们的会议是很少的 每周有个周会 但是平时不会有早会 晚会 我们开会的时间还是比较少的 但是业务团队,我之前也做过业务 业务团队的开会其实是比较多一点的 就像需求评审U评审还有很多评审 其实我们都是需要参与的 因为画面上你手机上或者说你做的需求上每个点 开发你其实都需要去了解数据是怎么来的 它整一块前后的逻辑 这样你才能更好的去做开发 明白了,目前能想到的就是这几个问题吧 我现在没有 好滴好滴 那我后面有再联系你 刚刚它整体回答其实还是比较好的 但是有一些细节的点 你们会发现回答的并没有那么好 但是我觉得问题已经不是很大了 就因为他整体回答是不错的 他回答很多细节的时候 他会去延伸,他自己把它回答出来了 像我之前去问他几个多线程的点 或者自己去往后面说了 这样会好很多 他整体来说算很不错 他不会的点 他跟你说了不会 但是你会觉得没关系 爱我请幅幅三连支持 爱请幟概三连支持