《互联网大厂Java面试:核心知识大考验》

50 阅读7分钟

面试官:第一轮提问开始。首先,讲讲Java中的多线程,在高并发场景下如何确保线程安全?

王铁牛:嗯……这个嘛,我觉得可以用synchronized关键字来同步代码块或者方法,保证同一时间只有一个线程能访问。

面试官:回答得不错。那再问个问题,线程池的核心参数有哪些,它们的作用分别是什么?

王铁牛:线程池的核心参数有corePoolSize、maximumPoolSize、keepAliveTime、unit和workQueue。corePoolSize是核心线程数,maximumPoolSize是最大线程数,keepAliveTime是线程池中的线程在空闲时的存活时间,unit是时间单位,workQueue是任务队列。

面试官:很好。最后一个问题,HashMap在多线程环境下会出现什么问题,如何解决?

王铁牛:HashMap在多线程环境下可能会出现死循环和数据丢失的问题。可以使用ConcurrentHashMap来替代。

面试官:第一轮提问结束。

面试官:第二轮提问。说说JVM的内存模型,各个区域的作用是什么?

王铁牛:JVM的内存模型包括堆、栈、方法区、程序计数器、本地方法栈。堆用于存储对象实例,栈用于存储局部变量和方法调用,方法区用于存储类信息、常量、静态变量等,程序计数器用于记录当前线程执行的字节码指令地址,本地方法栈用于执行本地方法。

面试官:还算有条理。那Spring框架中的IoC和AOP是什么,有什么作用?

王铁牛:IoC是控制反转,把对象的创建和依赖注入交给Spring容器。AOP是面向切面编程,用于在不修改原有代码的基础上增强功能。

面试官:还行。再问个问题,MyBatis的缓存机制是怎样的?

王铁牛:MyBatis有一级缓存和二级缓存。一级缓存是SqlSession级别的,二级缓存是Mapper级别的。

面试官:第二轮提问结束。

面试官:第三轮提问。Dubbo的集群容错策略有哪些,分别适用于什么场景?

王铁牛:Dubbo的集群容错策略有failover、failfast、failsafe、failback、forking。failover适用于读操作,failfast适用于非幂等写操作,failsafe适用于不重要的操作,failback适用于可重试的操作,forking适用于并行调用多个服务。

面试官:最后一个问题,Redis的数据结构有哪些,分别有什么特点和应用场景?

王铁牛:Redis的数据结构有字符串、哈希、列表、集合、有序集合。字符串适用于缓存、分布式锁等,哈希适用于存储对象,列表适用于消息队列、任务队列等,集合适用于去重、交集等,有序集合适用于排行榜等。

面试官:面试结束,回去等通知吧。

答案

多线程相关问题

  • synchronized关键字:用于同步代码块或者方法,确保同一时间只有一个线程能访问被同步的代码。它通过对象头中的Mark Word来实现,当一个线程访问被synchronized修饰的代码块或方法时,它会首先检查对象头中的Mark Word是否被设置为偏向锁状态,如果是,则该线程可以直接执行代码;如果不是,则该线程会通过CAS操作尝试将Mark Word设置为偏向锁状态,如果成功,则该线程可以直接执行代码;如果失败,则该线程会升级Mark Word为轻量级锁状态,然后通过自旋操作尝试获取锁,如果自旋一定次数后仍未获取到锁,则该线程会升级轻量级锁为重量级锁,此时其他线程会被阻塞,直到持有锁的线程释放锁。
  • 线程池核心参数
    • corePoolSize:核心线程数,当提交的任务数小于corePoolSize时,线程池会创建新的线程来执行任务。
    • maximumPoolSize:最大线程数,当提交的任务数大于corePoolSize时,线程池会将任务放入workQueue中,如果workQueue已满,且当前线程数小于maximumPoolSize,则会创建新的线程来执行任务。
    • keepAliveTime:线程池中的线程在空闲时的存活时间。
    • unit:时间单位,用于指定keepAliveTime的时间单位。
    • workQueue:任务队列,用于存储提交的任务,当提交的任务数大于corePoolSize时,线程池会将任务放入workQueue中。

HashMap相关问题

  • 多线程问题:HashMap在多线程环境下可能会出现死循环和数据丢失的问题。这是因为在扩容时,可能会导致链表形成环形结构,从而在get操作时出现死循环。同时,如果在扩容时多个线程同时操作,可能会导致数据丢失。
  • 解决方法:可以使用ConcurrentHashMap来替代HashMap,ConcurrentHashMap采用了分段锁的机制,提高了并发性能。

JVM内存模型相关问题

  • :用于存储对象实例,是JVM中最大的一块内存区域。
  • :用于存储局部变量和方法调用,每个线程都有自己独立的栈空间。
  • 方法区:用于存储类信息、常量、静态变量等,也被称为永久代(在JDK 8及以后被元空间取代)。
  • 程序计数器:用于记录当前线程执行的字节码指令地址,是线程私有的。
  • 本地方法栈:用于执行本地方法,也是线程私有的。

Spring相关问题

  • IoC(控制反转):把对象的创建和依赖注入交给Spring容器,降低了对象之间的耦合度。通过配置文件或注解来定义对象之间的依赖关系,Spring容器会根据这些配置来创建对象并注入依赖。
  • AOP(面向切面编程):用于在不修改原有代码的基础上增强功能。通过定义切面,将横切关注点(如日志、事务等)与业务逻辑分离,在程序运行时动态地织入这些切面。

MyBatis缓存机制相关问题

  • 一级缓存:是SqlSession级别的缓存,当一个SqlSession执行查询操作时,会先从一级缓存中查找,如果找到则直接返回结果,否则会执行数据库查询,并将结果存入一级缓存。
  • 二级缓存:是Mapper级别的缓存,多个SqlSession可以共享二级缓存。当一个SqlSession执行查询操作时,会先从一级缓存中查找,如果找不到则会从二级缓存中查找,如果找到则直接返回结果,否则会执行数据库查询,并将结果存入一级缓存和二级缓存。

Dubbo集群容错策略相关问题

  • failover:失败自动切换,适用于读操作。当调用失败时,会自动重试其他服务。
  • failfast:快速失败,适用于非幂等写操作。当调用失败时,会立即抛出异常,不再重试。
  • failsafe:失败安全,适用于不重要的操作。当调用失败时,会直接忽略,不抛出异常。
  • failback:失败自动恢复,适用于可重试的操作。当调用失败时,会将任务放入队列中,稍后重试。
  • forking:并行调用多个服务,适用于需要快速获取结果的场景。会同时调用多个服务,只要有一个成功就返回结果。

Redis数据结构相关问题

  • 字符串:适用于缓存、分布式锁等。是最基本的数据结构,支持GET、SET、INCR、DECR等操作。
  • 哈希:适用于存储对象。可以将对象的属性和值存储在哈希中,支持HGET、HSET、HDEL等操作。
  • 列表:适用于消息队列、任务队列等。是一个双向链表,支持LPUSH、RPOP、LRANGE等操作。
  • 集合:适用于去重、交集等。是一个无序的唯一元素集合,支持SADD、SMEMBERS、SINTER等操作。
  • 有序集合:适用于排行榜等。是一个有序的唯一元素集合,每个元素都有一个分数,支持ZADD、ZRANGE、ZRANK等操作。