面试官:请简要介绍一下 Java 中的多线程,以及在什么场景下你会选择使用多线程?
王铁牛:多线程就是在一个程序中同时运行多个线程。比如在电商系统中,当有大量用户同时下单时,可以使用多线程来处理订单,提高系统的响应速度。
面试官:很不错,回答得很清晰。那再问你,线程池有哪些核心参数,它们的作用分别是什么?
王铁牛:线程池的核心参数有 corePoolSize、maximumPoolSize、keepAliveTime、unit 和 workQueue。corePoolSize 是线程池的基本大小,maximumPoolSize 是线程池最大能容纳的线程数,keepAliveTime 是线程池中非核心线程的存活时间,unit 是存活时间的单位,workQueue 是任务队列。
面试官:很好,看来你对线程池有一定的了解。最后一个问题,如何合理配置线程池的参数?
王铁牛:嗯……这个嘛,要根据任务的类型和数量来配置。如果任务都是 CPU 密集型的,那线程池大小可以设置得小一些;如果任务是 I/O 密集型的,线程池大小可以设置得大一些。
面试官:好的,第一轮面试结束。接下来进入第二轮,说说 HashMap 的底层实现原理。
王铁牛:HashMap 底层是基于数组和链表实现的。当插入一个键值对时,会先通过哈希算法计算出键的哈希值,然后根据哈希值找到对应的数组位置。如果该位置为空,就直接插入;如果不为空,就会遍历链表,找到相同键的节点并更新其值。
面试官:那 HashMap 在扩容时会发生什么?
王铁牛:扩容时会创建一个新的更大的数组,然后将原数组中的元素重新哈希到新数组中。
面试官:扩容的时机是怎样确定的?
王铁牛:当 HashMap 中的元素个数超过阈值(threshold)时,就会触发扩容。阈值的计算方式是数组长度乘以负载因子(load factor)。
面试官:第二轮面试也结束了。现在进入第三轮,讲讲 Spring 中依赖注入的方式有哪些?
王铁牛:有构造器注入、Setter 方法注入和基于注解的注入。
面试官:基于注解的注入常用的注解有哪些?
王铁牛:有 @Autowired、@Qualifier、@Resource 等。
面试官:好的,本次面试就到这里。回去等通知吧。
答案:
- 多线程:多线程是指在一个程序中同时运行多个线程。在电商系统中,当大量用户同时下单时,使用多线程处理订单可以提高系统响应速度。一个 Java 程序至少有一个线程,即主线程。线程是程序执行的最小单元,一个进程可以包含多个线程。创建线程的方式有继承 Thread 类、实现 Runnable 接口和使用 Callable 接口。线程的生命周期包括新建、就绪、运行、阻塞和死亡。
- 线程池:线程池的核心参数有 corePoolSize、maximumPoolSize、keepAliveTime、unit 和 workQueue。corePoolSize 是线程池的基本大小,当提交的任务数小于 corePoolSize 时,线程池会创建新线程来执行任务。maximumPoolSize 是线程池最大能容纳的线程数,当提交的任务数大于 corePoolSize 时,会将任务放入 workQueue 中,如果 workQueue 已满且线程数小于 maximumPoolSize,则会创建新线程来执行任务。keepAliveTime 是线程池中非核心线程的存活时间,当线程数大于 corePoolSize 且线程空闲时间超过 keepAliveTime 时,非核心线程会被销毁。unit 是存活时间的单位,workQueue 是任务队列,用于存放提交的任务。合理配置线程池参数需要根据任务类型和数量来确定。如果任务是 CPU 密集型的,线程池大小可以设置得小一些;如果任务是 I/O 密集型的,线程池大小可以设置得大一些。
- HashMap:HashMap 底层是基于数组和链表实现的。当插入一个键值对时,会先通过哈希算法计算出键的哈希值,然后根据哈希值找到对应的数组位置。如果该位置为空,就直接插入;如果不为空,就会遍历链表,找到相同键的节点并更新其值。当 HashMap 中的元素个数超过阈值(threshold)时,就会触发扩容。阈值的计算方式是数组长度乘以负载因子(load factor)。扩容时会创建一个新的更大的数组,然后将原数组中的元素重新哈希到新数组中。
- Spring 依赖注入:依赖注入的方式有构造器注入、Setter 方法注入和基于注解的注入。构造器注入是通过构造函数来注入依赖对象,适用于依赖对象不能为空的情况。Setter 方法注入是通过 setter 方法来注入依赖对象,适用于依赖对象可以为空的情况。基于注解的注入常用的注解有 @Autowired、@Qualifier、@Resource 等。@Autowired 注解可以自动装配依赖对象,它会根据类型在容器中查找匹配的 bean。@Qualifier 注解用于指定要注入的 bean 的名称,当容器中有多个同类型的 bean 时,可以使用 @Qualifier 注解来指定具体要注入的 bean。@Resource 注解可以根据名称或类型来注入依赖对象,它的优先级是先按名称查找,如果找不到再按类型查找。