网站建设服务器有哪些,网页制作素材及流程,wordpress 标签固定链接,网站备案还要买幕布以下是几道针对Java并发编程的面试题#xff0c;涵盖基础知识、高级概念和实际应用场景#xff0c;适合资深Java工程师的面试评估#xff1a; 1. 线程池与任务调度
题目:
描述Java线程池的核心参数#xff08;如corePoolSize、maximumPoolSize、keepAliveTime等#xff…以下是几道针对Java并发编程的面试题涵盖基础知识、高级概念和实际应用场景适合资深Java工程师的面试评估 1. 线程池与任务调度
题目:
描述Java线程池的核心参数如corePoolSize、maximumPoolSize、keepAliveTime等的作用并说明如何根据业务场景选择合适的线程池类型如newFixedThreadPool、newCachedThreadPool。请解释以下代码片段中线程池的潜在问题并提出改进建议ExecutorService executor Executors.newFixedThreadPool(10);
for (int i 0; i 1000; i) {executor.submit(() - {// 执行耗时操作});
}参考答案: 核心参数作用 corePoolSize核心线程数线程池中始终存活的线程数量。maximumPoolSize最大线程数线程池允许创建的最大线程数。keepAliveTime非核心线程的存活时间超过核心数的线程在空闲后会被销毁。workQueue任务队列用于缓存未执行的任务。threadFactory线程工厂用于创建线程。handler拒绝策略当任务队列和线程数均满时的处理方式。 线程池类型选择 newFixedThreadPool固定大小的线程池适合负载稳定的场景如Web服务器。newCachedThreadPool可缓存的线程池适合短时任务如异步处理。newScheduledThreadPool支持定时任务适合周期性任务如定时清理缓存。 代码问题 使用newFixedThreadPool(10)提交1000个任务可能导致任务队列堆积默认使用无界队列LinkedBlockingQueue占用大量内存甚至导致OOM。改进建议 指定有界队列如ArrayBlockingQueue并设置合理的拒绝策略如CallerRunsPolicy。根据任务类型调整线程池大小如CPU密集型任务线程数为CPU核心数 1IO密集型任务线程数可更高。 2. 锁与同步机制
题目:
比较synchronized关键字和ReentrantLock的优缺点并说明在哪些场景下更适合使用ReentrantLock。请分析以下代码中的线程安全问题并提供解决方案public class Counter {private int count 0;public void increment() {count;}
}参考答案: synchronized vs ReentrantLock: 相同点都支持可重入性能解决线程安全问题。不同点 灵活性ReentrantLock支持尝试加锁tryLock、超时加锁、条件变量Condition等高级功能而synchronized只能通过隐式锁实现。性能在低竞争场景下synchronized性能接近ReentrantLock在高竞争场景下ReentrantLock可通过公平锁策略减少线程饥饿。使用方式synchronized通过语法糖实现如方法或代码块而ReentrantLock需要显式加锁和释放需在finally中释放。 代码问题 count操作即count count 1不是原子操作存在线程安全问题多个线程可能同时读取并更新count的旧值。解决方案 使用synchronized修饰increment方法。使用ReentrantLock手动加锁。使用原子类AtomicInteger替代普通int。 3. 并发工具类
题目:
请说明CountDownLatch、CyclicBarrier和Semaphore的使用场景及区别并提供一个实际应用案例。编写一个使用CyclicBarrier的示例代码模拟多个线程协作完成任务的场景。
参考答案: 工具类对比: CountDownLatch用于等待一组线程完成任务后继续执行如主线程等待所有子线程完成。CyclicBarrier用于多个线程相互等待达到屏障点后再同时继续执行如多线程并行计算后汇总结果。Semaphore用于控制同时访问某个资源的线程数量如限流。 案例 CyclicBarrier示例模拟3个线程分别计算数组的不同部分汇总结果后再输出public class CyclicBarrierExample {public static void main(String[] args) {CyclicBarrier barrier new CyclicBarrier(3, () - System.out.println(All threads have finished their part!));int[] data {1, 2, 3, 4, 5, 6};for (int i 0; i 3; i) {new Thread(() - {int sum 0;for (int j 0; j 2; j) {sum data[ThreadLocalRandom.current().nextInt(data.length)];}System.out.println(Thread Thread.currentThread().getId() computed sum: sum);try {barrier.await();} catch (Exception e) {e.printStackTrace();}}).start();}}
}4. 性能优化与死锁
题目:
如何通过JVM参数和工具如jstack、VisualVM定位和解决线程死锁问题请分析以下代码可能引发死锁的原因并提出优化方案public class Deadlock {private final Object lock1 new Object();private final Object lock2 new Object();public void methodA() {synchronized (lock1) {synchronized (lock2) {// 业务逻辑}}}public void methodB() {synchronized (lock2) {synchronized (lock1) {// 业务逻辑}}}
}参考答案: 死锁定位与解决: 使用jstack pid生成线程堆栈查找BLOCKED状态的线程及锁依赖关系。使用VisualVM的线程分析工具查看线程状态和锁竞争情况。解决方案避免嵌套锁或统一锁顺序如始终先获取lock1再获取lock2。 代码问题: 死锁原因methodA和methodB以相反顺序获取锁lock1→lock2 vs lock2→lock1可能导致两个线程互相等待对方释放锁。优化方案 统一锁顺序如始终先获取lock1再获取lock2。使用ReentrantLock.tryLock()尝试加锁超时后回退。 5. 高级并发模式
题目:
请描述生产者-消费者模型的实现方式并说明如何通过BlockingQueue优化该模型。使用CompletableFuture编写一个异步任务链要求 并行执行两个任务如查询数据库和查询缓存。合并结果并返回最终数据。
参考答案: 生产者-消费者模型: 使用BlockingQueue如ArrayBlockingQueue实现线程间通信生产者将任务放入队列消费者从队列取出任务处理。优点解耦生产者与消费者避免忙等busy-wait。 CompletableFuture示例: public class AsyncExample {public static void main(String[] args) {CompletableFutureString dbFuture CompletableFuture.supplyAsync(() - {// 模拟数据库查询return DB Result;});CompletableFutureString cacheFuture CompletableFuture.supplyAsync(() - {// 模拟缓存查询return Cache Result;});dbFuture.thenCombine(cacheFuture, (db, cache) - {// 合并结果return db cache;}).thenAccept(result - {System.out.println(Final Result: result);});}
}6. JVM与并发安全
题目:
解释volatile关键字的作用原理并说明它与synchronized在可见性、原子性和有序性上的区别。请分析以下代码为何不满足线程安全并提出改进方案public class VolatileExample {private volatile int counter 0;public void increment() {counter;}
}参考答案: volatile原理: volatile通过内存屏障Memory Barrier确保变量的可见性和禁止指令重排序但不保证原子性。与synchronized的区别: 可见性两者均保证可见性。原子性synchronized保证原子性volatile不保证。有序性volatile通过禁止指令重排序保证部分有序性而synchronized通过锁的释放和获取保证整体有序性。 代码问题: counter操作read → increment → write不是原子的即使counter是volatile多个线程仍可能覆盖彼此的修改。改进方案 使用synchronized修饰increment方法。使用原子类AtomicInteger。 7. 实战问题
题目:
设计一个线程安全的缓存类要求 支持并发读取和写入。提供过期时间TTL功能自动清除过期数据。支持高并发下的性能优化。
参考答案:
设计思路: 使用ConcurrentHashMap存储缓存数据键为缓存项的唯一标识值为带有TTL的封装对象。使用ReentrantReadWriteLock实现读写分离 读操作共享锁允许多线程并发读。写操作独占锁确保单线程写入。 使用定时任务如ScheduledExecutorService定期清理过期数据。代码示例: public class ConcurrentCacheK, V {private final ConcurrentHashMapK, CacheEntryV cache new ConcurrentHashMap();private final ReentrantReadWriteLock lock new ReentrantReadWriteLock();private final ScheduledExecutorService scheduler Executors.newScheduledThreadPool(1);public ConcurrentCache() {scheduler.scheduleAtFixedRate(this::cleanUp, 1, 1, TimeUnit.MINUTES);}public V get(K key) {lock.readLock().lock();try {CacheEntryV entry cache.get(key);if (entry null || entry.isExpired()) {return null;}return entry.getValue();} finally {lock.readLock().unlock();}}public void put(K key, V value, long ttl, TimeUnit unit) {lock.writeLock().lock();try {cache.put(key, new CacheEntry(value, System.currentTimeMillis() unit.toMillis(ttl)));} finally {lock.writeLock().unlock();}}private void cleanUp() {lock.writeLock().lock();try {cache.entrySet().removeIf(entry - entry.getValue().isExpired());} finally {lock.writeLock().unlock();}}private static class CacheEntryV {private final V value;private final long expireTime;public CacheEntry(V value, long expireTime) {this.value value;this.expireTime expireTime;}public V getValue() {return value;}public boolean isExpired() {return System.currentTimeMillis() expireTime;}}
}以上题目覆盖了Java并发编程的核心知识点包括线程池、锁机制、并发工具类、性能优化、死锁处理以及高阶设计模式。通过这些问题可以全面评估候选人对并发编程的理解和实际应用能力。