禾连科技一面面经
面经
写面经,攒人品
- 项目介绍
- 用到那些jdk版本?
- 1.8有哪些新特性?
- Stream API用到那些方法?
- Stream API并行情况?
- 用到那些集合?
- 用到那些线程安全的集合?
- threadlocal用在什么场景?
- threadlocal结构?
- 子线程能否拿到主线程threadlocal的内容?怎么拿?
- 为什么用dubbo?
- dubbo用什么做注册中心?
- 还有那些注册中心?
- dubbo启动扫描服务的过程?
- 同一个dubbo服务,不同的用户要使用,dubbo怎么做用户区分?
- 索引失效的情况?
- like对字段后半截查询(前半截模糊,后半截精确),如何优化?
- 为什么有young gc和old gc?
- 标记清除算法用在那个阶段?
- 反射有那些方法得到一个类?
- Class.forName和ClassLoader.loadclass的区别?
- 为什么要用Class.forName?使用场景?
- 为什么用rocketmq?
- rocketmq用在什么场景?
- 分布式锁怎么实现的?为什么没有用成熟的解决方案?
- 反问
解答
jdk1.8有哪些新特性?
1.8中添加了一些新的特性。
- Lambda表达式
- 函数式接口
- 方法引用和构造器引用(前三个一般联合使用)
- Stream API
- 接口中的默认方法和静态方法
- LocalDate API
- Optional类
- Base64 API
- 数组并行操作
- 永久代移除,增加元空间
Stream API用到那些方法?
Stream API并行情况?
常用的有哪些集合?
常用的集合主要可以分为4类,map、set、list和vector,hashtable等其他的。
常用的并发安全集合集合有哪些?
并发安全的集合有多种,也可以将不安全的集合转化为并发安全的集合。
- ConcurrentHashMap
- HashTable
- Collections.synchronizedCollection()方法转换
- StringBuffer
threadlocal用在什么场景?
ThreadLocal有两大典型使用场景。
- 场景1: 每个线程需要一个独享的对象(通常是工具类,典型需要使用的类有SimpleDateFormat和Random
SimpleDateFormat这种每个线程都需要使用,但是线程不安全的类
- 场景2: 每个线程内需要保存全局变量(例如在拦截器中获取用户信息),可以让不同方法直接使用,避免参数传递的麻烦。
threadlocal结构?
threadLocal底层采用了一个和线程绑定的ThreadLocalMap,这个map与线程绑定,每个线程都是自己,对自己的进行操作。
ThreadLocalMap的底层则是一个Entry数组,用threadlocal作为Entry的key,而值则是由我们控制。
子线程能否拿到主线程threadlocal的内容?怎么拿?
默认情况下,子线程是无法拿到主线程的ThreadLocal中的信息的,可以通过手动传递,ThreadLocal有一个子类,可以使用InheritableThreadLocal
,可以进行父子线程传递数据。
为什么用dubbo?
dubbo用什么做注册中心?
dubbo的注册中心有四种:
Nacos注册中心
Multicast注册中心
不需要启动任何中心节点,只要广播地址一样,就可以互相发现。
为了减少广播量,Dubbo缺省使用单播发送提供者地址信息给消费者,如果一个机器上同时启了多个消费者进程,消费者需声明unicast=false,否则只会有一个消费者能收到消息;当服务者和消费者运行在同一台机器上,消费者同样需要声明unicast=false,否则消费者无法收到消息,导致No provider available for the service
异常。Zookeeper注册中心
Redis注册中心
从2.1.0版本开始支持。
使用Redis的Key/Map结构存储数据结构。
使用Redis的Publish/Subscribe事件通知数据变更。Simple注册中心
Simple注册中心本身就是一个普通的Dubbo服务,可以减少第三方依赖,使整体通讯方式一致。
不支持集群https://dubbo.apache.org/zh/docs/v2.7/user/references/registry/
dubbo启动扫描服务的过程?
同一个dubbo服务,不同的用户要使用,dubbo怎么做用户区分?
对于这种情况,可以通过对相同的接口采用不同的版本进行区分。
索引失效的情况?
like对字段后半截查询(前半截模糊,后半截精确),如何优化?
一般而言在后半段模糊的情况下,like中的值可以根据前半段进行索引匹配,提高效率。
对于前半段模糊的情况,可以考虑使用覆盖索引,对like中的值和一个其他字段建立复合索引。
也考虑使用函数达到优化的效果:
1 | - LOCATE('substr',str,pos):返回substr在(pos后)str中第一次出现的位置,如果substr在str中不存在,返回值为0。 |
为什么有young gc和old gc?
GC是为了清理JVM在运行中产生的垃圾内存,回收使用。因为GC的效率问题,才会分为young gc和old gc。
相对而言,young gc速度快、次数多,而old gc速度慢、次数少、会停止任务的执行。
标记清除算法用在什么阶段?
标记清除算法一般用在老年代的垃圾回收,主要用在CMS垃圾回收器。
Class.forName和ClassLoader.loadclass的区别?
两者都是加载类的方法,ClassLoader.loadclass中会又三种类加载器,当前类加载器,指定类加载器,线程上下文类加载器。
Class.forName则是通过当前类加载器加载类的。底层会采用ClassLoader.loadclass。
Class.forName加载类的同时进行了初始化工作,ClassLoader.loadclass只加载进了内存中,ClassLoader.loadclass加载的类在用new关键字构造对象时才会初始化。
jdbc中规定,加载的同时需要将类注册进DriverManager中,ClassLoader.loadclass中没有类进行初始化,所以无法注册,不能使用。
- Class.forName和ClassLoader.loadClass
- 应用在JDBC的Class.forName和ClassLoader.loadClass区别
- Class.forName() 与 ClassLoader.loadClass()的区别
为什么要用Class.forName?使用场景?
Class.forName()
,是为了动态加载类,在数据库驱动场景中使用较多,一般在动态加载类后还需要调用newInstance()
方法来实例化对象。
Class.forName()
返回的是类,newInstance()
返回的是实例化的对象。
newInstance()
方法返回的对象是弱类型,而new
返回的对象是强类型。
java中有三种获得类的方法:
- Class Object = object.getClass();
- Class Object = Object.class;
- Class Object = Class.forName(“java.lang.Object”);
为什么使用rocketmq?rocketmq用在什么场景?
分布式锁怎么实现的?为什么没有用成熟的解决方案?
参考文献 & 鸣谢
- 多线程并发下的线程安全的集合类的使用
- 你了解 JDK 8 Stream 数据流效率吗?千万级数据量性能如何?
- Java8 Stream 数据流,大数据量下的性能效率怎么样?
- JDK 8 Stream 数据流效率怎么样?
- 20 个实例玩转 Java 8 Stream
- 深度掌握java stream 流操作,让你的代码高出一个逼格!
- Java版本:JDK8的十大新特性介绍
- JDK1.8 新特性(全)
- Minor GC、Young GC、Full GC、Old GC、Major GC、Mixed GC傻傻分不清
- Class.forName和ClassLoader.loadClass
- 应用在JDBC的Class.forName和ClassLoader.loadClass区别
- Class.forName() 与 ClassLoader.loadClass()的区别
- https://dubbo.apache.org/zh/docs/v2.7/user/references/registry/