面试官:第一轮提问开始。首先,说一下 Java 中多线程的实现方式有哪些?
王铁牛:这个我知道,有继承 Thread 类和实现 Runnable 接口这两种方式。
面试官:不错,回答正确。那再问一个,在多线程环境下,如何保证线程安全?
王铁牛:可以使用 synchronized 关键字,还有就是用 Lock 接口及其实现类。
面试官:很好。最后一个问题,简述一下线程池的工作原理。
王铁牛:线程池就是预先创建一定数量的线程,当有任务来的时候,从线程池中获取线程去执行任务,执行完后线程不会销毁,而是继续待在池中等待下一个任务。
面试官:好,第一轮提问结束。下面进入第二轮提问。说说 HashMap 的底层数据结构。
王铁牛:它底层是数组加链表,后来链表长度大于 8 且数组长度大于 64 时,链表会转换为红黑树。
面试官:嗯,回答得还行。那 ArrayList 是线程安全的吗?为什么?
王铁牛:不是,因为它的方法没有加锁,多线程操作时可能会出现数据不一致的情况。
面试官:还算说得过去。再问一个,Spring 框架的核心特性有哪些?
王铁牛:这个……好像是依赖注入和面向切面编程吧。
面试官:第二轮提问完毕。现在是第三轮提问。简述一下 JVM 的内存结构。
王铁牛:有堆、栈、方法区这些。
面试官:具体说说堆内存又分为哪些区域?
王铁牛:不太清楚,大概就是新生代、老年代这些吧。
面试官:最后一个问题,Dubbo 的服务注册与发现原理是什么?
王铁牛:呃……不太明白,乱说一个,是不是通过 Zookeeper 来实现的?
面试官:好,三轮提问都结束了。回去等通知吧。
答案:
- Java 多线程实现方式:
- 继承 Thread 类:创建一个类继承 Thread 类,重写 run 方法,在 run 方法中编写线程执行的代码。然后通过创建该类的实例对象,调用 start 方法启动线程。
- 实现 Runnable 接口:创建一个类实现 Runnable 接口,实现 run 方法。再创建 Thread 类的实例对象时,将实现了 Runnable 接口的类的实例作为参数传入,调用 Thread 的 start 方法启动线程。
- 多线程保证线程安全的方法:
- synchronized 关键字:可以修饰方法或代码块。修饰方法时,该方法在同一时刻只能被一个线程访问;修饰代码块时,指定要锁定的对象,确保在同一时刻只有一个线程能执行该代码块。
- Lock 接口及其实现类:如 ReentrantLock,通过 lock 方法获取锁,unlock 方法释放锁。可以实现更灵活的锁控制,比如可中断锁、定时锁等。
- 线程池工作原理:线程池预先创建一定数量的线程,当提交任务时,线程池从线程队列中获取线程去执行任务。如果线程池中的线程数量小于核心线程数,会创建新线程执行任务;如果线程数达到核心线程数,任务会被放入阻塞队列中;如果阻塞队列已满,且线程数小于最大线程数,则会创建新线程执行任务;如果线程数达到最大线程数,任务会根据拒绝策略进行处理,如抛出异常、使用调用者线程执行等。
- HashMap 底层数据结构:底层是数组加链表,在 JDK1.8 后链表长度大于 8 且数组长度大于 64 时,链表会转换为红黑树。数组中的每个元素是一个 Node 节点,包含键值对等信息。在插入元素时,通过计算键的哈希值,找到对应的数组下标位置,如果该位置为空,则直接插入新节点;如果不为空,则通过链表或红黑树的方式插入。
- ArrayList 是否线程安全及原因:ArrayList 不是线程安全的。因为它的方法没有加锁,在多线程环境下,当多个线程同时对其进行读写操作时,可能会出现数据不一致的情况,比如一个线程在添加元素时,另一个线程可能同时在删除元素,导致数据混乱。
- Spring 框架核心特性:
- 依赖注入(DI):通过控制反转(IoC)容器,将对象之间的依赖关系由程序主动创建改为由容器注入,降低了对象之间的耦合度。
- 面向切面编程(AOP):将横切关注点(如日志、事务等)与业务逻辑分离,通过切面和切点的定义,在不修改业务代码的情况下增强业务功能。
- JVM 内存结构:
- 堆:是 JVM 中最大的一块内存区域,被所有线程共享。主要用于存储对象实例和数组。堆又分为新生代、老年代和永久代(JDK1.8 后为元空间)。
- 栈:每个线程都有自己独立的栈空间,用于存储局部变量、方法调用等。
- 方法区:存储类信息、常量、静态变量等数据。
- Dubbo 服务注册与发现原理:Dubbo 基于 Zookeeper 实现服务注册与发现。服务提供者启动时,会将自己的服务信息注册到 Zookeeper 中,包括服务接口、实现类、服务地址等。服务消费者启动时,会从 Zookeeper 中订阅自己需要的服务信息,当服务提供者的服务信息发生变化时,Zookeeper 会通知服务消费者,从而实现服务的动态发现和调用。