Java线程池详解

这篇文章和大家讲讲Java中的线程池:

常见的4中线程池:

1.Executors.newCachedThreadPool();
创建一个可缓存的线程池,如果线程长度超过处理需求,可灵活处理回收空闲线程,若无可回收线程,则新建线程;
在这里插入图片描述
2.Executors.newFixedThreadPool(5);
创建指定数量的线程池,可控制线程最大并发数,超出的线程会在队列中等待;
在这里插入图片描述
3.Executors.newScheduledThreadPool(10);
创建一个定长线程池,支持定时及周期性任务回收;
在这里插入图片描述
可知道多长时间后执行,专门做定时任务的线程池;
4.Executors.newSingleThreadExecutor();
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务
在这里插入图片描述
5.**Executors.defaultThreadFactory();**默认线程池
在这里插入图片描述

创建线程池的2钟方法:

  1. 第一种:
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static class Thread01 extends Thread{
    @Override
    public void run() {
        System.out.println("当前线程"+Thread.currentThread().getId());
        int i = 10/2;
        System.out.println("运行线程"+i);
    }
}
public static class Runnable01 implements Runnable{
    @Override
    public void run() {
        System.out.println("当前线程"+Thread.currentThread().getId());
        int i = 10/2;
        System.out.println("运行线程"+i);
    }
}

启动:

service.execute(new Thread01());
service.execute(new Runnable01());
  1. 第二种
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
        200,
        10,
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(10000),
        Executors.defaultThreadFactory(),
        new ThreadPoolExecutor.AbortPolicy());

此种方法创建的线程池有7大参数,我们知道了其意义,才可合理的运用他,我们进入其底层实现,如图 :
在这里插入图片描述

  • int corePoolSize:核心线程数,其一直会在线程池保存(即时系统空闲,除非设置了allowCoreThreadTimeOut),即线程池创建以后就准备就绪的线程数量,就等待来接收异步任务.
  • int maximumPoolSize:最大线程数量,控制资源.
  • Long keepAliveTime:存活时间,如果当前的线程数量>核心数量,释放空闲线程(maximumPoolSize-corePoolSize)(只要线程空闲>存活时间).
  • TimeUnit unit:存活时间单位. BlockingQueue
  • workQueue:阻塞队列,如果任务有很多,多余的任务会先放在队列中,有线程空闲后,便会从队列中取新的线程继续执行.
  • ThreadFactory threadFactory:线程创建工厂. RejectedExecutionHandler
  • handler(拒绝策略):如果队列满了,存不了更多的任务,按照我们指定的拒绝策略拒绝执行我们的任务.

拒绝策略:

在这里插入图片描述
默认util包下有4种拒绝策略:
1.丢弃最老的任务
2.直接丢弃新来的任务,并且抛出异常
3.直接调用run方法的策略,相当于做了同步调用
4.直接丢弃新来的任务,但不 抛出异常

线程池工作顺序/流程:

1.线程池首先创建,准备好corePoolSize数量的核心线程,准备接收任务;
2.新来的任务,用corePoolSize准备好的空闲线程执行.
2.1 如果corePoolSize被任务占满,就将任务放在阻塞队列中,一旦有空闲的corePoolSize线程,便自己去任务对列中获取任务执行
2.2如果阻塞队列也满了,就直接开新线程执行,最大只能开到maximumPoolSize;
2.3如果maximumPoolSize也满了,maximumPoolSize-corePoolSize数量的空闲线程会在keepAliveTime指定的时间后自动销毁,最终保持到corePoolSize数量的线程.
2.4 如果线程开到了maximumPoolSize数量,还有新的任务进来,就会使用reject指定的拒绝策略来进行处理;
3所以线程的创建都是由threadFactory创建.

注意:new LinkedBlockingQueue<>();默认是Integer的最大值;(可能导致内存不够,故一定要存为定值数量)

使用线程池的好处:

  1. 降低资源消耗
    通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
  2. 提高响应速度
    因为线程池中的线程没有没有超过线程池的最大上限时,有的线程处于等待分配任务状态,当任务来临时无需创建新的线程就能执行;
  3. 提高线程的可管理性
    线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销;无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,

笔者刚开始运营公众号啦,感兴趣的可关注我的公众号,欢迎交流!

image.png

### Java 线程池详解 #### 创建线程池的方式 Java 提供了几种创建线程池的方法,最常用的是通过 `Executors` 工厂类来获取预配置好的线程池实例。然而,在实际项目中更推荐使用 `ThreadPoolExecutor` 构造器来自定义参数,以获得更好的灵活性和性能控制[^1]。 ```java // 不推荐的做法:固定大小的缓存线程池可能导致资源浪费或耗尽 ExecutorService cachedPool = Executors.newCachedThreadPool(); // 推荐做法:自定义 ThreadPoolExecutor 参数设置 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build(); ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, namedThreadFactory); ``` #### 关键组件说明 - **核心线程数 (`corePoolSize`)** 定义了即使处于空闲状态也会被保留在线程池中的最小线程数量。 - **最大线程数 (`maximumPoolSize`)** 设置允许的最大活动线程数目;当现有任务队列已满而又有新的提交任务时才会触发扩容至该上限。 - **存活时间 (`keepAliveTime`)** 非核心线程闲置后的自动回收等待周期长度。 - **阻塞队列 (`workQueue`)** 存储待处理的任务对象集合,不同类型的队列会影响吞吐量表现及拒绝策略行为。 - **线程工厂 (`threadFactory`)** 负责生产新线程实体,默认实现较为简单,通常建议开发者根据应用场景定制化命名规则以便于调试跟踪。 #### 常见错误与优化技巧 忽视对线程池内部运行状况监控是常见的失误之一。应当定期审查并调整相关参数,确保其适应当前负载需求变化趋势。另外需要注意捕获未预见异常情形下的恢复机制设计,防止因个别失败案例影响整体服务稳定性[^2]。 #### 实践指南 对于Web容器如Tomcat而言,内置有经过优化过的专用线程管理模块用于支撑高并发请求场景下高效运作的要求。尽管如此,了解基础概念仍然有助于更好地理解框架底层运作机理,并能在必要时候做出针对性调优措施。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值