禾连科技一面面经

面经

写面经,攒人品

  1. 项目介绍
  2. 用到那些jdk版本?
  3. 1.8有哪些新特性?
  4. Stream API用到那些方法?
  5. Stream API并行情况?
  6. 用到那些集合?
  7. 用到那些线程安全的集合?
  8. threadlocal用在什么场景?
  9. threadlocal结构?
  10. 子线程能否拿到主线程threadlocal的内容?怎么拿?
  11. 为什么用dubbo?
  12. dubbo用什么做注册中心?
  13. 还有那些注册中心?
  14. dubbo启动扫描服务的过程?
  15. 同一个dubbo服务,不同的用户要使用,dubbo怎么做用户区分?
  16. 索引失效的情况?
  17. like对字段后半截查询(前半截模糊,后半截精确),如何优化?
  18. 为什么有young gc和old gc?
  19. 标记清除算法用在那个阶段?
  20. 反射有那些方法得到一个类?
  21. Class.forName和ClassLoader.loadclass的区别?
  22. 为什么要用Class.forName?使用场景?
  23. 为什么用rocketmq?
  24. rocketmq用在什么场景?
  25. 分布式锁怎么实现的?为什么没有用成熟的解决方案?
  26. 反问

解答

jdk1.8有哪些新特性?

  1.8中添加了一些新的特性。

  • Lambda表达式
  • 函数式接口
  • 方法引用和构造器引用(前三个一般联合使用)
  • Stream API
  • 接口中的默认方法和静态方法
  • LocalDate API
  • Optional类
  • Base64 API
  • 数组并行操作
  • 永久代移除,增加元空间

Stream API用到那些方法?

StreamAPI
StreamAPI

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
2
3
4
5
6
7
8
- LOCATE('substr',str,pos):返回substr在(pos后)str中第一次出现的位置,如果substr在str中不存在,返回值为0
> SELECT `column` FROM `table` WHERE LOCATE('keyword', `field`)>0
- POSITION('substr' IN `field`)
> SELECT `column` FROM `table` WHERE POSITION('keyword' IN `filed`)
- INSTR(`str`,'substr')
> SELECT `column` FROM `table` WHERE INSTR(`field`, 'keyword' )>0
- FIND_IN_SET(str1,str2):返回str2中str1所在的位置索引,其中str2必须以","分割开。
> SELECT * FROM `person` WHERE FIND_IN_SET('keyword',`field`);

为什么有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?使用场景?

  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用在什么场景?

分布式锁怎么实现的?为什么没有用成熟的解决方案?


参考文献 & 鸣谢