阿里回合肥的一个面试官,牙科的项目,公司内部项目想开发成能拿出去和其他医院合作来赚钱
下午三点 线下面试
Java高级开发工程师 10-15K
工作职责:
- 负责公司平台和业务系统开发,并主导落地实施;
- 深入发掘和分析业务需求,撰写技术方案和系统设计;
- 参与技术方案和系统设计评审;把握复杂系统的设计,确保系统的架构质量;
- 系统代码编写;解决疑难问题;
- 对负责的业务有主人翁意识,对现存或未来系统进行宏观的思考,形成统一的框架、平台或组件;
- 为团队引入创新的技术、创新的解决方案,用创新的思路解决问题。 任职资格:
- Java基础扎实,理解io、多线程、集合等基础框架,对JVM原理有一定的了解;熟悉面向对象设计开发;
- 3年以上使用JAVA开发的经验,对于你用过的主要的开源框架,能了解到原理和机制的层面;
- 熟悉分布式系统的设计和应用,熟悉分布式、缓存、消息、搜索、推荐等机制;能对分布式常用技术进行合理应用,解决问题;
- 掌握Linux操作系统和数据库分库分表技术;有较强的分析设计能力和方案整合能力;
- 良好的沟通技能,团队合作能力,勤奋好学;
- 对互联网或J2EE应用开发的最新潮流有关注,喜欢去看及尝试最新的技术,追求编写优雅的代码,从技术趋势和思路上能影响技术团队;
- 有面向电商交易,商品,营销,会员,订单,C端产品等相关平台研发经验者有先。
- 同时具备一定数据计算能力,算法经验、熟悉AI技术者优先。
1.java中的锁有哪些
synchronized、reentrantLock
synchronized
核心特性
隐式锁:通过 synchronized 关键字实现,自动获取和释放锁。
可重入性:同一线程可多次获取同一锁,避免死锁。
非公平锁:默认不保证等待线程的公平性。
锁升级:JDK 6 后引入偏向锁、轻量级锁、重量级锁的自适应机制。
锁升级
偏向锁:标记对象头,减少无竞争时的同步开销。
轻量级锁:通过 CAS 操作尝试获取锁,避免线程阻塞。
重量级锁:依赖操作系统 Mutex 实现,线程进入阻塞状态。
使用示例
// 修饰代码块
synchronized (obj) { ... }
// 修饰方法(锁为当前对象实例或类对象)
public synchronized void method() { ... }
优缺点
优点:简单易用,JVM 自动优化,无需手动释放。
缺点:无法中断等待锁的线程,无法设置超时,缺乏灵活性。
reentrantLock
核心特性
显式锁:需手动调用 lock() 和 unlock()。
可中断:支持响应中断(lockInterruptibly())。
可超时:尝试非阻塞获取锁(tryLock(long, TimeUnit))。
公平性:可选择公平锁(默认非公平)。
条件变量:通过 newCondition() 创建多个 Condition。
使用示例
ReentrantLock lock = new ReentrantLock(true); // 公平锁
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock(); // 必须手动释放
}
优缺点
优点:灵活性高,支持超时、中断、公平性,多条件变量。
缺点:需手动管理锁,容易忘记释放导致死锁。
ReadWriteLock(读写锁)
StampedLock(邮戳锁)
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 实现方式 | 内置关键字,JVM自动管理锁的获取与释放 | 显式使用 lock() 和 unlock() 方法来管理 |
| 可中断性 | 不可中断,获取锁时无法响应中断 | 可以响应中断,使用 lockInterruptibly() 可实现 |
| 公平性 | 默认非公平锁 | 可以设置为公平锁,也可以是非公平锁 |
| 锁粒度 | 锁住方法或代码块 | 更细粒度的锁控制,支持条件变量等高级特性 |
| 性能 | 在高并发情况下可能性能较差 | 在高并发场景下性能更好,提供更多灵活性 |
| 重入性 | 支持,线程再次请求锁不会死锁 | 支持,线程再次请求锁不会死锁 |
| 条件变量支持 | 不支持条件变量 | 支持条件变量,提供 Condition 对象用于等待/通知机制 |
| 特性 | 公平锁 (Fair Lock) | 非公平锁 (Non-Fair Lock) |
|---|---|---|
| 锁获取顺序 | 严格按照请求锁的顺序(先来先得) | 不严格按顺序,可能后请求的线程先获得锁 |
| 性能 | 性能较差,可能导致更多的上下文切换 | 性能较好,减少了排队和上下文切换的时间 |
| 饥饿现象 | 防止饥饿现象(每个线程都会获得锁) | 可能会出现饥饿现象(某些线程可能一直无法获得锁) |
| 实现复杂度 | 实现相对复杂,调度的开销较大 | 实现简单,效率较高 |
| 使用场景 | 需要严格控制线程执行顺序,避免饥饿现象 | 对性能要求较高,不关心线程顺序 |
2.spring原理
IOC控制反转
AOP面向切面编程
**控制反转(IoC)**:通过容器管理对象生命周期和依赖关系。
**面向切面编程(AOP)**:分离横切关注点,增强代码模块化。
**声明式编程**:通过注解简化配置(如事务、AOP)。
**模块化设计**:各组件(如 MVC、Security、Data)独立可扩展。
3.线程池种类
- **FixedThreadPool**:适用于任务数固定且持续的场景。
- **CachedThreadPool**:适用于任务数量不固定、短时间任务较多的场景。
- **SingleThreadExecutor**:适用于需要顺序执行任务的场景。
- **ScheduledThreadPool**:适用于定时任务和周期性任务的场景。
- **WorkStealingPool**:适用于高并发、大量短小任务的场景。
- **自定义线程池**:适用于需要精细控制线程池参数的复杂场景。
4.任务到线程池执行过程
1. 提交任务 -> 2. 任务进入队列 -> 3. 线程选择任务 -> 4. 执行任务 -> 5. 返回执行结果 -> 6. 线程回收或重用
核心线程数 (`corePoolSize) 达到时,线程池首先会将新任务放入 等待队列,如果队列已满且线程池的线程数小于最大线程数,则创建新的线程。
最大线程数 (maximumPoolSize) 达到时,新的任务会被拒绝执行(默认抛出异常),除非采用了自定义的拒绝策略。
5.分布式锁过期处理
6.jvm调优
-Xms:设置JVM堆的初始大小。
-Xmx:设置JVM堆的最大大小。
-XX:MetaspaceSize=<size>:设置Metaspace的初始大小。
-XX:MaxMetaspaceSize=<size>:设置Metaspace的最大大小。
jmap 查看堆内存存活对象情况
jstat -gc 查看GC次数
7.垃圾回收算法,jdk8默认垃圾回收器
jdk8默认是Parallel GC 多线程标记复制清除
CMS 并发标记
G1 分区回收
8.最左前缀原则
复合索引(A,B,C)
查询 A B 走索引
查询 B C 不走索引
查询 A C MySQL 会使用索引中的 A 部分来过滤数据,但它不会利用到 C 列的索引。
9.innodb原理
b+tree 平衡多路搜索树
10.主键索引、其他索引有啥区别
主键索引、普通索引、唯一索引
| 特性 | 主键索引 | 其他索引(如普通索引、唯一索引、全文索引) |
|---|---|---|
| 唯一性 | 唯一,不能为空 | 普通索引允许重复值;唯一索引保证唯一,允许 NULL |
| 索引类型 | 聚集索引(Clustered Index) | 非聚集索引(Non-clustered Index) |
| 数量限制 | 每个表只能有一个主键索引 | 一个表可以有多个索引 |
| 数据存储方式 | 数据按主键顺序存储,叶节点存储数据行 | 索引叶节点存储的是索引值,指向数据行的地址 |
| NULL 值 | 不允许 NULL 值 | 普通索引允许 NULL,唯一索引允许多个 NULL 值 |
| 性能优化 | 用于唯一标识记录,性能非常高 | 用于加速特定查询,取决于索引的设计 |
| 使用场景 | 唯一标识记录,如 ID、订单号等 | 提高查询效率,适用于没有 NULL 值或需要查找某些字段的查询 |