Java并发编程常见面试题解析

线程基础

  1. 解释线程和进程的区别?

进程是操作系统资源分配的基本单位,而线程是CPU调度的基本单位。一个进程可以包含多个线程,它们共享进程的资源,但拥有独立的程序计数器、堆栈和局部变量等。

  1. 描述线程的生命周期及其状态转换?

线程的生命周期包括新建、就绪、运行、阻塞和终止五种状态。

- 新建:线程对象已创建但尚未启动。

- 就绪:线程具备运行条件,等待CPU调度。

- 运行:线程获得CPU资源正在执行。

- 阻塞:线程因某种原因暂停执行,例如等待IO或获取锁。

- 终止:线程执行完毕或异常退出。

  1. 如何创建和启动线程?

可以通过继承Thread类或实现Runnable接口来创建线程,并调用start()方法启动线程。

线程同步

  1. 什么是线程安全问题?

当多个线程同时访问共享资源,且至少有一个线程进行写操作时,就可能出现数据不一致的问题,这就是线程安全问题。

  1. 解释 synchronized 关键字的作用?

synchronized关键字用于实现线程同步,它可以保证同一时刻只有一个线程执行被修饰的代码块或方法,从而避免数据竞争。

  1. volatile 关键字有什么作用?

volatile关键字保证了变量的可见性和禁止指令重排序,确保线程读取到的变量值是最新的。

  1. 介绍几种常见的线程安全集合类?

  2. Vector、Hashtable:早期版本提供的线程安全集合类,效率较低。

  3. ConcurrentHashMap、CopyOnWriteArrayList:基于更细粒度锁机制实现的线程安全集合类,效率更高。

线程池

  1. 为什么要使用线程池?

线程池可以减少线程创建和销毁的开销,提高系统资源利用率,并方便线程管理。

  1. 解释线程池的核心参数?

  2. corePoolSize:核心线程数。

  3. maximumPoolSize:最大线程数。
  4. keepAliveTime:非核心线程闲置超时时间。
  5. workQueue:任务队列。
  6. threadFactory:线程工厂,用于创建线程。
  7. handler:拒绝策略,当线程池已满且任务队列也满时如何处理新任务。

  8. 介绍几种常见的线程池拒绝策略?

  9. AbortPolicy:直接抛出RejectedExecutionException异常。

  10. DiscardPolicy:丢弃新任务。
  11. DiscardOldestPolicy:丢弃队列中最老的任务,然后重试。
  12. CallerRunsPolicy:由调用线程执行任务。

并发工具类

  1. CountDownLatch 的作用是什么?

CountDownLatch允许一个或多个线程等待其他线程完成操作后再继续执行。

  1. CyclicBarrier 和 CountDownLatch 的区别?

CountDownLatch 用于一次性的计数控制,而 CyclicBarrier 可以重复使用,用于线程间相互等待。

  1. Semaphore 的作用是什么?

Semaphore 用于控制并发线程数,可以通过 permits 数量限制对资源的访问。

  1. Exchanger 的作用是什么?

Exchanger 允许两个线程在同步点交换数据。

其他

  1. ThreadLocal 的作用是什么?

ThreadLocal 为每个线程提供独立的变量副本,避免线程间数据共享问题。

  1. 什么是死锁?如何避免死锁?

当两个或多个线程互相持有对方需要的资源,导致程序无法继续执行,这就是死锁。避免死锁的方法包括:

- 避免循环等待资源。

- 使用超时机制获取资源。

- 使用资源分配图进行分析。

总结

并发编程是Java开发中的重要内容,掌握线程基础、同步机制、线程池、并发工具类等知识点是应对面试的关键。