线程池的介绍

线程池的概念

线程池是一种多线程使用模式,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。不同的线程池启动线程和停止线程的模式不一样,整体而言线程池会提供空闲线程执行任务。


线程池的工作机制

 

  1. 线程池模式下,接受任务的主体是线程池,线程池将任务分配给线程。
  2. 线程池负责线程的启动,停止,状态监管,任务分配。

         
线程池的优势


         线程池提供线程的创建,启动,执行,停止,并发等管理功能,使用线程池可以避免系统线程管理的开销和风险。降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行;

Java线程池详解


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

corePoolSize(线程池基本大小):在任务队列未满之前,线程池维护的线程数量。创建方式可以是按需创建,也可以是初始化创建。按需创建,当有新任务提交给线程池时,如果线程数小于corePoolSize,线程池会创建新的线程来提供服务。
maximumPoolSize(线程池最大大小):在任务队列满后,线程池无空闲线程提供服务,此时会创建新的线程来提供服务,线程最大数不能超过maximumPoolSize。
keepAliveTime(线程存活保持时间):maximumPoolSize-corePoolSize数量线程的存活时间,当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。

workQueue(任务队列):用于传输和保存等待执行任务的阻塞队列。

handler(线程饱和策略):当线程池和队列都满了,再加入任务会执行此策略。


线程池为什么要使用阻塞队列而不使用非阻塞队列

         首先不阻塞队列是个什么情况这个我没想象出来,这个就像我们去快餐店吃饭,客人不多的时候,营业员可以直接为我们服务(无阻塞队列),人多的时候,要排队然后依次为我们服务。如果人再多那就添加店员为我们服务,一切都是顺理成章。对于线程池来说。阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入wait状态,释放cpu资源。
线程池配置技巧

这个跟线程池的任务类型有关,线程池任务类型从宏观上说可以分为CPU密集型和IO密集型两种。CPU密集型任务,一般为CPU核心数+1。IO密集型任务可以使用稍大的线程池,一般为2*CPU核心数。

java中提供的线程池


Executors类提供了4种不同的线程池:CachedThreadPool, FixedThreadPool, ScheduledThreadPool, SingleThreadExecutor

  • CachedThreadPool:适用于负载较轻,执行短期异步任务的场景。
  • FixedThreadPool:适用于负载较重的场景,避免线程切换,创建带来的性能消耗。
  • ScheduledThreadPool:适用于执行延时或者周期性任务。
  • SingleThreadExecutor:适用于顺序执行的场景。
`ForkJoinPool.commonPool()` 是 Java 7 引入的 `ForkJoinPool` 类中的一个**静态公共线程池实例**,从 Java 8 开始,它被广泛用于 `CompletableFuture`、并行流(`parallelStream()`)等并发任务中作为**默认的异步执行线程池**。 --- ### ✅ 基本介绍 `ForkJoinPool.commonPool()` 是一个**工作窃取(work-stealing)线程池**,它的核心特点是: - 使用多个线程来执行任务。 - 每个线程维护自己的任务队列。 - 当某个线程的任务队列为空时,它可以从其他线程的任务队列“窃取”任务执行,从而提高并发效率。 --- ### ✅ 创建与配置 `commonPool` 是在 JVM 启动时自动创建的,其默认的线程数量由以下因素决定: - **默认线程数 = CPU 核心数 - 1** - 例如,在一个 4 核 CPU 上,默认创建 3 个线程。 你可以通过 JVM 启动参数修改其线程数量: ```bash -Djava.util.concurrent.ForkJoinPool.common.parallelism=5 ``` --- ### ✅ 特点 | 特性 | 描述 | |------|------| | 线程数量 | 默认是 CPU 核心数 - 1 | | 工作机制 | 工作窃取(Work-Stealing)算法 | | 使用场景 | 并行流、CompletableFuture、ForkJoinTask | | 是否可自定义 | 可以通过 JVM 参数调整,但不能替换 commonPool 实例 | | 线程类型 | 守护线程(daemon threads) | --- ### ✅ 示例:查看 commonPool 的线程数 ```java import java.util.concurrent.ForkJoinPool; public class CommonPoolDemo { public static void main(String[] args) { ForkJoinPool pool = ForkJoinPool.commonPool(); System.out.println("并行度(Parallelism): " + pool.getParallelism()); System.out.println("是否是公共池: " + (pool == ForkJoinPool.commonPool())); } } ``` --- ### ✅ 在 CompletableFuture 中的使用 当你调用: ```java CompletableFuture.runAsync(() -> { System.out.println("执行线程:" + Thread.currentThread().getName()); }); ``` 底层使用的就是: ```java ForkJoinPool.commonPool().execute(() -> { ... }); ``` --- ### ✅ 注意事项 1. **不要在 commonPool 中执行阻塞任务** 因为会阻塞线程,影响其他任务执行效率。推荐使用自定义线程池。 2. **避免资源竞争** 多个模块共用一个线程池,可能会互相影响性能。 3. **线程名不易区分** commonPool 的线程名称是 `ForkJoinPool.commonPool-worker-n`,不利于调试。 --- ### ✅ 替代方案:自定义线程池 ```java ExecutorService customPool = Executors.newFixedThreadPool(4); CompletableFuture.runAsync(() -> { System.out.println("使用自定义线程池:" + Thread.currentThread().getName()); }, customPool); ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值