线程池核心原理详解

为什么需要线程池

我们知道相比较进程而言,线程是操作系统调度的更细粒度的资源,如果通过大量手动创建、调用线程,显然线程资源的复用,线程如何更好管理等问题就出现了。所以能不能有一种机制既能解决实现线程的复用,以及线程管理呢,这就提出线程池的概念,类比还有像其他基于池化思想的:数据库连接池,Http连接池等

线程池创建多线程

通常使用Executors工具类创建一个线程池,该类提供多种类型线程池的创建方法,主要分析一下3种

   //创建一个包含指定线程数的线程池(单池多线程)
   public static ExecutorService newFixedThreadPool(int nThreads)
   
   //创建一个只包含一个工作线程的线程池(单池单线程)
   public static ExecutorService newSingleThreadExecutor()
   
   //创建一个能自动扩容的线程池
   public static ExecutorService newCachedThreadPool()

查看源码,这三个方法底层本质都是依赖ThreadPoolExecutor,所以自定义线程池的话,我们重点关注ThreadPoolExecutor类就行,并且在阿里巴巴手册也推荐使用ThreadPoolExecutor构建一个线程池,因为它更灵活,可读性更高,适用更多的需求场景。后面会深入理解ThreadPoolExecutor,来了解线程池的整个工作原理

ThreadPoolExecutor线程池工作原理

在这里插入图片描述
工作流程:
ThreadPoolExecutor执行execute方法分下面4种情况
1.如果当前运行的线程数小于corePool,直接创建新线程来执行提交的任务
2.如果当前运行的线程数大于或等于corePool,将任务加入阻塞队列
3.如果无法加入任务到阻塞队列(队列已满),创建新的线程来执行任务
4.如果创建的线程数超过了maximumPool,任务将被拒绝,调用RejectedExecutionHandler.rejectedExecution()方法

ThreadPoolExecutor核心参数分析

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

corePoolSize:核心线程数
maximumPool:线程池能够容纳的最大线程数
BlockingQueue:用来暂时保存任务的阻塞队列
keepAliveTime:空闲线程存活时间
unit:时间单位
ThreadFactory:线程工厂
RejectedExecutionHandler:拒绝策略,当任务队列已满并且达到最大线程数后,线程池会调用相应的拒绝策略,可以分为以下几种策略

  • AbortPolicy(默认):抛出RejectedExecutionException异常吗,程序终止
  • CallerRunsPolicy:不抛弃任务,交给原来的调用者调用
  • DiscardOldestPolicy:抛弃队列中排队最久的任务,然后将当前任务添加到队列,再次尝试提交
  • DiscardPolicy:默默丢弃任务,不予处理,不抛异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值