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

40 阅读7分钟

面试官:请简要介绍一下Java中的多线程机制,以及如何创建一个线程?

王铁牛:多线程就是一个程序中同时运行多个线程呗。创建线程可以通过继承Thread类或者实现Runnable接口。

面试官:嗯,回答得还算清晰。那说说线程池的原理和作用吧。

王铁牛:线程池就是预先创建一些线程,当有任务来的时候就从线程池里拿线程去执行任务。作用就是提高效率,减少线程创建和销毁的开销。

面试官:还不错。再问个关于JVM的问题,什么是垃圾回收机制?

王铁牛:垃圾回收就是把那些不再使用的对象内存给回收掉。

第一轮结束

面试官:接下来深入一点,讲讲JVM的内存模型都有哪些部分?

王铁牛:嗯……有堆、栈、方法区啥的吧。

面试官:具体说说堆内存的分区情况。

王铁牛:呃,这个不太清楚,大概分新生代、老年代吧。

面试官:说说Spring框架中IoC容器的作用和实现原理。

王铁牛:IoC容器就是管理对象呗,实现原理不太明白。

第二轮结束

面试官:讲讲MyBatis框架的核心组件和工作流程。

王铁牛:核心组件有啥来着,工作流程也不太记得了。

面试官:说说Dubbo的服务注册与发现机制。

王铁牛:这个,不太清楚咋说。

面试官:最后问个Redis的问题,Redis的数据类型有哪些,应用场景分别是什么?

王铁牛:数据类型好像有字符串、哈希啥的,应用场景不太会说。

第三轮结束

面试结束后,面试官表示会让王铁牛回家等通知。从面试过程来看,王铁牛对于一些基础的Java知识有一定了解,但在面对深入的、复杂的问题时,回答得比较模糊和混乱,整体表现不太理想,还需要进一步加强对Java核心知识、JUC、JVM、多线程、线程池、HashMap、ArrayList、Spring、SpringBoot、MyBatis、Dubbo、RabbitMq、xxl - job、Redis等技术的学习和理解,才能更好地应对互联网大厂的面试。

答案:

  • 多线程机制及创建线程
    • 多线程是指在一个程序中同时运行多个线程,每个线程独立执行不同的任务。
    • 创建线程的方式主要有两种:
      • 继承Thread类:通过继承Thread类并重写其run方法来定义线程的执行逻辑。示例代码如下:
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("这是一个通过继承Thread类创建的线程");
    }
}
// 使用时:
MyThread thread = new MyThread();
thread.start();
    - 实现Runnable接口:实现Runnable接口的类需要重写run方法,然后将该类的实例作为参数传递给Thread类的构造函数来创建线程。示例代码如下:
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("这是一个通过实现Runnable接口创建的线程");
    }
}
// 使用时:
Thread thread = new Thread(new MyRunnable());
thread.start();
  • 线程池的原理和作用
    • 原理:线程池预先创建一定数量的线程,当有任务提交时,从线程池中获取线程来执行任务。线程执行完任务后不会被销毁,而是返回线程池等待下一个任务。这样可以避免频繁地创建和销毁线程,从而提高系统性能。
    • 作用:
      • 提高效率:减少线程创建和销毁的开销。
      • 便于管理:可以对线程池中的线程数量、任务队列等进行统一管理和控制。
  • JVM的垃圾回收机制
    • 垃圾回收机制是Java虚拟机自动回收不再使用的对象所占用的内存空间的过程。当一个对象不再被任何引用指向时,就会被视为垃圾对象,等待垃圾回收器进行回收。
  • JVM的内存模型
    • 主要包括堆、栈、方法区、程序计数器等部分。
    • 堆内存:是Java对象存储的地方,被划分为新生代、老年代和永久代(Java 8之后为元空间)。
      • 新生代:主要存放新创建的对象,又分为Eden区和两个 Survivor区。新对象首先在Eden区创建,当Eden区满时,会触发Minor GC(新生代垃圾回收),将存活的对象复制到其中一个Survivor区。如果Survivor区也满了,会将年龄较大的对象晋升到老年代。
      • 老年代:存放生命周期较长的对象。当新生代的对象经过多次垃圾回收后仍然存活,就会被晋升到老年代。
      • 永久代(元空间):用于存储类信息、常量、静态变量等。在Java 8之后,永久代被元空间取代,元空间使用本地内存,不再受限于JVM的内存大小。
  • Spring框架中IoC容器的作用和实现原理
    • 作用:IoC(控制反转)容器负责创建、配置和管理对象之间的依赖关系,将对象的创建和依赖注入的控制权从应用程序转移到Spring容器。这样可以降低对象之间的耦合度,提高代码的可维护性和可测试性。
    • 实现原理:
      • 通过XML配置文件或注解定义对象及其依赖关系。
      • 使用反射机制在运行时动态创建对象,并根据配置进行依赖注入。例如,当一个类的某个属性被标记为@Autowired注解时,Spring容器会自动查找并注入与之匹配的对象。
  • MyBatis框架的核心组件和工作流程
    • 核心组件:
      • SqlSessionFactory:创建SqlSession的工厂,负责加载MyBatis的配置文件,构建Executor等。
      • SqlSession:代表与数据库的一次会话,提供了执行SQL语句、管理事务等方法。
      • Mapper接口和XML映射文件:Mapper接口定义了操作数据库的方法签名,XML映射文件则具体实现这些方法对应的SQL语句。
    • 工作流程:
      • 应用程序通过SqlSessionFactory创建SqlSession。
      • SqlSession通过Executor执行SQL语句。Executor会根据配置选择合适的执行器(如SimpleExecutor、ReuseExecutor、BatchExecutor)。
      • 根据SQL语句的参数,通过ParameterHandler设置参数。
      • 执行SQL语句后,通过ResultSetHandler处理结果集,将结果映射为Java对象返回给应用程序。
  • Dubbo的服务注册与发现机制
    • 服务注册:服务提供者将自己提供的服务信息(包括服务接口、实现类、服务地址等)注册到注册中心。注册中心可以是Zookeeper、Nacos等。例如,服务提供者使用Dubbo的注解或配置文件声明服务接口和实现类,并指定注册中心的地址,然后通过Dubbo的服务导出功能将服务注册到注册中心。
    • 服务发现:服务消费者从注册中心获取服务提供者的地址列表。当服务消费者调用服务时,Dubbo会根据负载均衡策略从地址列表中选择一个服务提供者进行调用。例如,服务消费者通过Dubbo的@Reference注解引用服务接口,Dubbo会自动从注册中心查找并获取可用的服务提供者地址,然后进行远程调用。
  • Redis的数据类型及应用场景
    • 字符串(String):最基本的数据类型,可以存储任何形式的数据,如数字、字符串、二进制数据等。应用场景包括缓存、分布式锁、计数器等。例如,缓存热点数据、实现分布式锁(通过SETNX命令)、记录网站访问量等。
    • 哈希(Hash):适合存储对象,将对象的属性和值存储在一个哈希表中。常用于存储对象信息,如用户信息、商品信息等。
    • 列表(List):是一个有序的字符串列表,可以从列表的两端进行插入和删除操作。应用场景有消息队列、任务队列等。例如,实现简单的消息队列,生产者向列表右侧插入消息,消费者从列表左侧读取消息。
    • 集合(Set):是无序的、唯一的字符串集合,支持交集、并集、差集等操作。常用于去重、社交关系等场景。例如,统计用户的共同好友、去除重复数据等。
    • 有序集合(Sorted Set):和集合类似,但每个元素都关联一个分数,通过分数进行排序。应用场景有排行榜、热门列表等。例如,实现文章阅读量排行榜,根据阅读量为每个文章设置分数,通过Sorted Set进行排序。