面试官:第一轮面试开始,首先问你,说说Java中的多线程有哪些实现方式?
王铁牛:嗯,有继承Thread类和实现Runnable接口这两种方式。
面试官:回答得不错。那再问你,线程池有哪些核心参数?
王铁牛:这个我知道,有corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。
面试官:很好。最后一个问题,简述一下HashMap的底层实现原理。
王铁牛:HashMap底层是数组加链表再加红黑树,当链表长度大于8且数组长度大于64时,链表会转换为红黑树。
面试官:好,第一轮面试结束。
面试官:第二轮面试,讲讲JVM的内存结构。
王铁牛:呃,有堆、栈、方法区这些。
面试官:那类加载机制有哪些?
王铁牛:嗯……有双亲委派模型之类的吧。
面试官:不太清晰,Spring框架中,依赖注入有几种方式?
王铁牛:好像有构造器注入和setter注入。
面试官:第二轮面试结束。
面试官:第三轮面试,MyBatis的动态SQL有哪些?
王铁牛:这个……不太记得了。
面试官:Dubbo的集群容错策略有哪些?
王铁牛:嗯……想不起来了。
面试官:RabbitMq的消息确认机制了解吗?
王铁牛:不太清楚。
面试官:好,面试结束,回去等通知吧。
答案:
- Java多线程实现方式:
- 继承Thread类:通过继承Thread类,并重写其run方法来定义线程执行的任务。
- 实现Runnable接口:实现Runnable接口的run方法,将该实现类实例作为参数传递给Thread类的构造函数来创建线程。
- 线程池核心参数:
- corePoolSize:线程池的核心线程数,当提交的任务数小于corePoolSize时,线程池会创建新线程来执行任务。
- maximumPoolSize:线程池的最大线程数,当提交的任务数大于corePoolSize且workQueue已满时,会创建新线程直到线程数达到maximumPoolSize。
- keepAliveTime:线程池中的线程在空闲时的存活时间。
- unit:keepAliveTime的时间单位。
- workQueue:用于存放任务的队列。
- threadFactory:用于创建线程的工厂。
- handler:当线程池无法处理新任务时的拒绝策略。
- HashMap底层实现原理:
- 数组:HashMap底层使用数组来存储键值对。
- 链表:当两个或多个键值对的哈希值相同时,会在数组的同一个位置形成链表。
- 红黑树:当链表长度大于8且数组长度大于64时,链表会转换为红黑树,以提高查找效率。
- JVM内存结构:
- 堆:存放对象实例,是垃圾回收的主要区域。
- 栈:存放局部变量、方法调用等。
- 方法区:存储类信息、常量、静态变量等。
- 类加载机制:
- 双亲委派模型:类加载器加载类时,先委托父类加载器加载,只有父类加载器无法加载时才自己加载。
- Spring依赖注入方式:
- 构造器注入:通过构造函数传入依赖对象。
- setter注入:通过setter方法设置依赖对象。
- MyBatis动态SQL:
- if:根据条件判断是否拼接SQL语句。
- where:智能处理where子句,避免多余的and或or。
- foreach:用于循环遍历集合。
- Dubbo集群容错策略:
- failover:失败自动切换,重试其他服务器。
- failfast:快速失败,只调用一次,失败立即报错。
- failsafe:失败安全,出现异常直接忽略。
- failback:失败自动恢复,后台定时重试。
- RabbitMq消息确认机制:
- 生产者确认:确保消息成功发送到Broker。
- 消费者确认:消费者收到消息后向Broker发送确认,有自动确认和手动确认两种方式。