简要说下线程池的任务执行机制?

线程池旨在通过复用一组线程来执行多项任务,以提高性能、提高资源利用率并简化线程管理。Java 中的线程池通常由 ThreadPoolExecutor 类实现。下面我将简要描述线程池的任务执行机制。

核心组成

ThreadPoolExecutor 是 Java 并发包中的核心类,其任务执行机制包括以下几个核心组成部分:

  1. 核心线程 (Core Threads):在核心线程池大小(corePoolSize)范围内,线程池会优先启动核心线程执行任务,核心线程会始终保持存活,除非设置了 allowCoreThreadTimeOut
  2. 最大线程 (Maximum Threads):当任务队列满了且当前核心线程已用尽,线程池可以创建超出的线程,但最大不超过 maximumPoolSize
  3. 任务队列 (Work Queue):用于保存等待执行的任务。常见的队列有 LinkedBlockingQueueArrayBlockingQueueSynchronousQueue等。
  4. 拒绝策略 (RejectedExecutionHandler):当任务无法执行时,会触发拒绝策略,处理新提交的任务。

执行机制

线程池的任务执行机制可以总结为以下几个步骤:

  1. 提交任务: 任务被提交到线程池。

    threadPoolExecutor.submit(task);
    
  2. 判断核心线程:

    • 如果当前运行的线程数量小于 corePoolSize,即使有空闲线程,也会新建一个核心线程来执行任务。
  3. 任务入队列:

    • 如果当前运行的线程数量等于或超过 corePoolSize,则将任务加入到任务队列 workQueue
  4. 判断最大线程和任务队列:

    • 如果任务队列已满且当前运行的线程数量小于 maximumPoolSize,仍会新建线程来处理任务。
    • 如果任务队列已满且当前运行的线程数量大于或等于 maximumPoolSize,将触发拒绝策略 handler
  5. 执行任务:

    • 空闲线程从队列中获取任务并执行。
    • 核心线程会一直存活并处理任务,即使处于空闲状态。
    • 非核心线程在执行完任务且超过 keepAliveTime 的空闲时间后会被终止。

状态转换

线程池的状态转换主要涉及以下几个状态:

  • RUNNING:接受新任务和处理队列中的任务。
  • SHUTDOWN:不接受新任务,但会处理队列中的任务。
  • STOP:不接受新任务且不处理队列中的任务,并且会中断正在进行的任务。
  • TIDYING:所有任务终止,workerCount 为 0,执行钩子方法 terminated
  • TERMINATEDterminated 方法执行完毕状态。

详细示例

以下是一个简单示例,展示了线程池如何处理任务:

import java.util.concurrent.*;

public class ThreadPoolMechanismExample {
    public static void main(String[] args) {
        // 配置参数
        int corePoolSize = 2;
        int maximumPoolSize = 4;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                handler);

        // 提交任务
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i;
            threadPool.submit(() -> {
                try {
                    System.out.println("Task " + taskNumber + " is running by " + Thread.currentThread().getName());
                    Thread.sleep(2000); // 模拟任务执行时间
                    System.out.println("Task " + taskNumber + " is completed by " + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 关闭线程池
        threadPool.shutdown();
        try {
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                threadPool.shutdownNow();
            }
        } catch (InterruptedException ex) {
            threadPool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

小结

  • 当任务提交给线程池时,线程池首先检查当前运行的线程数,如果少于 corePoolSize,则创建新线程处理任务。
  • 如果运行的线程已达 corePoolSize,任务会被放入任务队列 workQueue
  • 如果任务队列满了且线程数目少于 maximumPoolSize,则会创建新的线程处理任务。
  • 如果任务队列满了且线程数目已达 maximumPoolSize,则会根据指定的拒绝策略处理新任务。

理解线程池的任务执行机制对高效地使用线程池类至关重要,有助于在并发编程中获得更好的性能和资源管理效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java奋斗者

听说打赏我的人再也不会有BUG

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值