Java常见线程池简介、线程池创建、线程池原理、死锁产生原因及排查
发布日期:2021-05-15 00:00:42 浏览次数:29 分类:精选文章

本文共 2598 字,大约阅读时间需要 8 分钟。

线程池与死锁深度分析

一、线程池创建与执行机制

1. 线程池是线程的管理池
  • 核心线程数与非核心线程数:核心线程为专门获取任务并执行的线程,非核心线程用于处理超出核心线程负载的任务。
  • 任务处理策略:任务到达时,首先检查是否有核心线程空闲,否则将任务加入队列。队列满时,若超过最大线程数,采用饱和策略。
2. 阻塞队列类型对比
  • ArrayBlockingQueue:基于数组实现的有界FIFO队列,特点是固定大小和内存限制。
  • LinkedBlockingQueue:基于链表实现,支持大容量,性能优于ArrayBlockingQueue。
  • DelayQueue:支持延迟执行,按执行时间排序。
  • SynchronousQueue:不存储任务,要求生产者与消费者同步,效率更高。
3. 线程池执行流程
  • 线程池创建后,立即处理任务。
  • 任务提交时:
    • 若核心线程数未达最大,直接启动新线程。
    • 若核心线程已满,存入队列。
    • 若队列满,且总线程未达最大值,扩展非核心线程。
  • 处理完成后,线程返回到队列获取下一个任务。
  • 空闲线程若超过核心线程数,将超出部分线程销毁,当任务完成后,最小化到核心线程数。
  • 4. 常见线程池类型应用介绍
    • newFixedThreadPool:定长线程池,适合长期任务。
    • newCachedThreadPool:可缓存线程池,适合短期任务。
    • newSingleThreadExecutor:单线程池,顺序执行任务。
    • newScheduledThreadPool:定长线程池,支持定时任务。

    二、线程池创建方法实例

    // 创建年度线程池
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
    2, // 核心线程数
    5, // 最大线程数
    1L, // 空闲时间(秒)
    TimeUnit.SECONDS,
    new LinkedBlockingDeque<>(3),
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.AbortPolicy()
    );

    三、饱和拒绝策略

    // 饱和拒绝策略选择
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
    2,
    5,
    1L,
    TimeUnit.SECONDS,
    new SynchronousQueue(),
    Executors.defaultThreadFactory(),
    new CallerRunsPolicy()
    );

    四、死锁实例

    // 死锁示例代码
    class ThreadA implements Runnable {
    private String lockA, lockB;
    public ThreadA(String lockA, String lockB) {
    this.lockA = lockA;
    this.lockB = lockB;
    }
    @Override
    public void run() {
    synchronized (lockA) {
    System.out.println(Thread.currentThread().getName() + "持有了lockA,尝试获取lockB");
    try {
    synchronized (lockB) {
    System.out.println(Thread.currentThread().getName() + "已经获取了lockB");
    }
    } catch (InterruptedException e) {
    System.out.println("线程被打断:" + Thread.currentThread().getName());
    Thread.currentThread().interrupt();
    }
    }
    }
    }
    public class DeadlockTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
    String lockA = "lockA", lockB = "lockB";
    Thread thread1 = new Thread(new ThreadA(lockA, lockB), "(locale1)");
    Thread thread2 = new Thread(new ThreadA(lockB, lockA), "(locale2)");
    thread1.start();
    thread2.start();
    try {
    Thread.sleep(2000);
    } catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    }
    System.out.println("主线程等待死锁情况");
    }
    }

    五、死锁排查方法

  • 使用堆转储工具(如开源工具JDK的Sampler)。
  • 导出线程堆转储文件,查看处于等待状态的线程。
  • 识别死锁资源,分析原因。
  • 优化代码,减少资源竞争或顺序依赖。
  • 通过以上方法,可以有效识别并消除死锁问题,确保系统稳定运行。

    上一篇:Java一对多情况下,使用EasyPoi实现Excel合并单元格完成导出功能
    下一篇:JVM类加载器及JVM内存模型简介

    发表评论

    最新留言

    路过,博主的博客真漂亮。。
    [***.116.15.85]2025年05月04日 01时05分26秒