线程并发—线程池

本文深入探讨线程池的概念,解释其如何通过预创建线程以提高性能和资源利用率。详细介绍了ThreadPoolExecutor类的使用,包括核心参数的含义与功能,以及线程池的拒绝策略。同时,提供了Executors工具类创建线程池的方法,便于理解和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文作者:黄海燕,叩丁狼高级讲师。原创文章,转载请注明出处。

1.1 为什么要使用线程池?

所谓线程池,其实和连接池的概念很像,就是在内存中实现创建好了多个线程,我们使用的时候直接从里面拿,不用的时候直接放回去,并且线程池我们是可以进行管理的,很好的控制多个线程,并且减少了创建和销毁的过程减小了内存中的消耗。

相比起普通的创建线程,线程池的好处:

  • 重用存在的线程,减少对象创建、消亡的开销,性能佳。
  • 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
  • 提供定时执行、定期执行、单线程、并发数控制等功能。

1.2 线程池常用类体系结构:

image.png

1.3 ThreadPoolExecutor类

Executor接口表示线程池,而ThreadPoolExecutor为Executor接口最常用的实现类。所以学线程池不能不先学习ThreadPoolExecutor。

ThreadPoolExecutor类中有四个公共的构造器,也就是我们可以通过访问构造器创建对象。

image.png

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {}
参数参数描述
int corePoolSize:表示允许线程池中允许同时运行的最大线程数。(线程池的核心池大小,在创建线程池之后,线程池默认没有任何线程。当有任务过来的时候才会去创建创建线程执行任务。换个说法,线程池创建之后,线程池中的线程数为0,当任务过来就会创建一个线程去执行,直到线程数达到corePoolSize 之后,就会被到达的任务放在队列中。)
int maximumPoolSize:线程池允许的最大线程数,他表示最大能创建多少个线程。maximumPoolSize肯定是大于等于corePoolSize。
long keepAliveTime:表示线程没有任务时最多保持多久然后停止。默认情况下,只有线程池中线程数大于corePoolSize时,keepAliveTime才会起作用。换句话说,当线程池中的线程数大于corePoolSize,并且一个线程空闲时间达到了keepAliveTime,那么就是shutdown。
TimeUnit unit:约束keepAliveTime的时间单位,如:时、分、秒
BlockingQueue workQueue:一个阻塞队列,用来存储等待执行的任务,当线程池中的线程数超过它的corePoolSize的时候,线程会进入阻塞队列进行阻塞等待。通过workQueue,线程池实现了阻塞功能。阻塞队列选择:ArrayBlockingQueue;LinkedBlockingQueue;SynchronousQueue;PriorityBlockingQueue;
ThreadFactory threadFactory:线程工厂,创建线程的对象
RejectedExecutionHandler handler:拒绝处理任务时的策略。

简单使用:

public class Demo {
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5,10,0,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(10));
        for (int i = 0;i<50;i++){
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }
        pool.shutdown();
    }
}

抛出异常:

报错原因是因为最大线程数只有10,任务数为50,任务数>最大线程数据时线程池会启用拒绝策略,我们没有传入拒绝策略,所以使用了默认策略AbortPolicy。

拒绝策略:

ThreadPoolExecutor内部类内部类的描述
ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy什么都不做,丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy线程池为停止,丢弃队列最前面的任务,然后重新尝试执行任务
ThreadPoolExecutor.CallerRunsPolicy线程池为停止,由调用本线程处理该任务,本线程调用任务的run方法。

1.4使用Executors创建创建线程池Executors线程池工具类,提供了一系列静态工厂方法用于创建各种线程池。列表如下:

方法名方法描述
newFixedThreadPool(int nThreads)创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newWorkStealingPool(int parallelism)创建持有足够线程的线程池来支持给定的并行级别,并通过使用多个队列,减少竞争,它需要穿一个并行级别的参数,如果不传,则被设定为默认的CPU数量。ForkJoinPool支持大任务分解成小任务的线程池
newSingleThreadExecutor()创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行****
newCachedThreadPool()创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程可以重复利用执行任务。默认为60s未使用就被终止和移除
newSingleThreadScheduledExecutor()创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
newScheduledThreadPool(int corePoolSize) 创建一个定长线程池,支持定时及周期性任务执行。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值