尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Java并发编程面试12大核心知识点解析

Java并发编程面试12大核心知识点解析 1. 并发编程面试核心知识体系在技术面试中并发编程始终是考察重点和难点。作为拥有10年Java开发经验的面试官我总结了并发面试中最常被问及的12个核心知识点这些内容覆盖了90%以上的并发面试问题。本文将采用原理剖析代码示例面试话术的三维讲解方式让你在面试中游刃有余。2. 线程基础与生命周期2.1 线程与进程的本质区别进程是操作系统资源分配的基本单位而线程是CPU调度的最小单位。关键区别在于进程拥有独立的地址空间线程共享进程资源线程上下文切换成本远低于进程约1/10进程间通信需要IPC机制线程可直接读写共享数据// 查看Java程序默认线程 ThreadMXBean threadMXBean ManagementFactory.getThreadMXBean(); ThreadInfo[] threadInfos threadMXBean.dumpAllThreads(false, false); for (ThreadInfo threadInfo : threadInfos) { System.out.println(threadInfo.getThreadId() : threadInfo.getThreadName()); } /* 典型输出 5: Attach Listener 4: Signal Dispatcher 3: Finalizer 2: Reference Handler 1: main */2.2 线程状态转换机制Java线程的6种状态及其转换条件NEW新建未启动RUNNABLE可运行包含操作系统层面的Running/ReadyBLOCKED同步阻塞WAITING无限等待TIMED_WAITING超时等待TERMINATED终止面试技巧被问到线程有几种状态时应先说明Java定义6种再解释操作系统层面其实只有3种基本状态就绪、运行、阻塞3. 线程安全与锁机制3.1 synchronized实现原理synchronized的锁升级过程无锁新创建对象偏向锁记录线程ID减少CAS操作轻量级锁自旋尝试获取锁重量级锁线程阻塞进入等待队列// 锁对象头结构示例 |-------------------------------------------------------|--------------------| | Mark Word (64 bits) | State | |-------------------------------------------------------|--------------------| | unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 | Normal | | thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 | Biased | | ptr_to_lock_record:62 | lock:2 | Lightweight Locked | | ptr_to_heavyweight_monitor:62 | lock:2 | Heavyweight Locked | | | lock:2 | Marked for GC |3.2 ReentrantLock与AQS体系AbstractQueuedSynchronizerAQS是Java并发包的核心其关键组成state同步状态volatile修饰CLH队列线程等待队列ConditionObject条件变量// ReentrantLock公平锁实现示例 final void lock() { acquire(1); } public final void acquire(int arg) { if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }4. 并发工具类实战4.1 CountDownLatch vs CyclicBarrier对比维度CountDownLatchCyclicBarrier计数方式递减计数递增计数重置机制不可重复使用可循环使用阻塞线程调用await()的线程所有参与的线程典型应用场景主线程等待子任务完成多线程相互等待// CyclicBarrier示例多线程数据汇总 CyclicBarrier barrier new CyclicBarrier(3, () - { System.out.println(所有分片处理完成开始汇总); }); IntStream.range(0,3).forEach(i - new Thread(() - { try { System.out.println(分片i处理完成); barrier.await(); } catch (Exception e) { e.printStackTrace(); } }).start());4.2 ThreadLocal内存泄漏防范ThreadLocal使用不当会导致内存泄漏强引用链Thread - ThreadLocalMap - Entry - ValueEntry对Key是弱引用但Value仍是强引用正确使用姿势try { threadLocal.set(obj); // ...业务逻辑 } finally { threadLocal.remove(); // 必须显式清理 }5. 并发容器精讲5.1 ConcurrentHashMap演进JDK7与JDK8实现对比JDK7分段锁Segment默认16个段JDK8CAS synchronized锁头节点链表转红黑树阈值8扩容时多线程协助// JDK8 putVal关键代码 if (binCount ! 0) { if (binCount TREEIFY_THRESHOLD) treeifyBin(tab, i); if (oldVal ! null) return oldVal; break; }5.2 CopyOnWriteArrayList适用场景适用读多写少的场景写入时复制整个数组// 写入操作源码 public boolean add(E e) { final ReentrantLock lock this.lock; lock.lock(); try { Object[] elements getArray(); int len elements.length; Object[] newElements Arrays.copyOf(elements, len 1); newElements[len] e; setArray(newElements); return true; } finally { lock.unlock(); } }6. 原子操作类原理6.1 CAS的ABA问题典型ABA问题场景线程1读取值A线程2修改A→B→A线程1CAS操作仍然成功解决方案AtomicStampedReferenceAtomicStampedReferenceInteger asr new AtomicStampedReference(100, 0); int stamp asr.getStamp(); asr.compareAndSet(100, 101, stamp, stamp1); // 版本号控制6.2 LongAdder高性能原理相比AtomicLong的改进分散竞争多个Cell数组最终一致性sum()时汇总所有Cell值适合高并发统计场景7. 线程池深度解析7.1 核心参数配置公式理想线程数计算CPU密集型N_cpu 1IO密集型N_cpu * (1 WT/ST)WT等待时间ST计算时间// 自定义线程池示例 ThreadPoolExecutor executor new ThreadPoolExecutor( 4, // corePoolSize 8, // maximumPoolSize 60, // keepAliveTime TimeUnit.SECONDS, new ArrayBlockingQueue(100), // 有界队列 new ThreadFactoryBuilder().setNameFormat(order-pool-%d).build(), new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 );7.2 工作队列选型对比队列类型特性适用场景SynchronousQueue无容量直接移交高响应优先级任务LinkedBlockingQueue无界队列默认Integer.MAX任务量波动较大ArrayBlockingQueue有界队列防止资源耗尽PriorityBlockingQueue优先级队列任务有优先级区分8. 死锁预防与排查8.1 死锁产生的必要条件互斥条件资源独占请求与保持持有资源并申请新资源不剥夺条件资源只能自愿释放循环等待形成等待环8.2 诊断工具使用jstack定位死锁jstack -l pid | grep -A 10 deadlockJConsole线程监测检测线程阻塞状态查看锁持有情况9. 面试高频问题解析9.1 volatile关键字保证可见性和有序性内存屏障写屏障确保写操作前的指令不会重排到后面读屏障确保读操作后的指令不会重排到前面// 单例模式双重检查 class Singleton { private volatile static Singleton instance; public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }9.2 happens-before规则Java内存模型的8大规则程序顺序规则锁规则volatile规则线程启动规则线程终止规则中断规则终结器规则传递性10. 实战案例分析10.1 电商库存扣减方案// 分布式锁实现库存扣减 public boolean deductStock(Long itemId, int num) { String lockKey stock: itemId; try { // 获取分布式锁 boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, 10, TimeUnit.SECONDS); if (!locked) return false; // 查询库存 Integer stock stockMapper.selectById(itemId); if (stock num) return false; // 扣减库存 stockMapper.updateStock(itemId, num); return true; } finally { redisTemplate.delete(lockKey); } }10.2 百万级日志处理// 多阶段并行处理日志 CompletableFutureVoid task CompletableFuture .supplyAsync(() - readLogFiles(), readExecutor) .thenApplyAsync(logs - filterValidLogs(logs), processExecutor) .thenAcceptAsync(result - saveToDB(result), writeExecutor); task.exceptionally(ex - { System.err.println(处理异常: ex.getMessage()); return null; });11. 性能优化技巧11.1 锁优化实践减小锁粒度从方法级→代码块级锁分离读写锁分离ReentrantReadWriteLock锁消除JIT编译器优化锁粗化合并连续锁操作11.2 上下文切换统计# Linux查看上下文切换 vmstat 1 # 关键指标 # cs - 上下文切换次数 # in - 中断次数优化建议避免过度创建线程使用协程Quasar/Kotlin协程减少锁竞争12. 前沿技术展望12.1 协程技术对比技术特点代表实现线程内核态调度开销大Java Thread协程用户态调度轻量级Kotlin Coroutines虚拟线程JVM管理的轻量级线程Project Loom12.2 Java19虚拟线程// 虚拟线程使用示例 try (var executor Executors.newVirtualThreadPerTaskExecutor()) { IntStream.range(0, 10_000).forEach(i - { executor.submit(() - { Thread.sleep(Duration.ofSeconds(1)); return i; }); }); }在实际面试中除了掌握这些技术点外更重要的是能够结合项目经验讲述你是如何解决具体并发问题的。建议准备2-3个真实的并发场景案例按照问题现象-分析过程-解决方案-效果验证的结构组织你的回答这会让面试官看到你的实战能力。
返回列表