线程池执行原理

本文深入探讨Java线程池的工作原理,包括ThreadPoolExecutor的execute()方法、线程池状态控制(ctl)以及线程复用机制。通过分析源码,揭示线程池如何管理线程,执行任务,以及在不同状态下如何处理任务队列。

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

前言

在刚接触多线程编程时,曾写过类似于如下代码:

public static void main(String[] args) throws InterruptedException {
   
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 20, 1, TimeUnit.HOURS, new LinkedBlockingDeque<>());
    Thread thread = new Thread(() -> System.out.println("子线程运行"));
    poolExecutor.submit(thread);
    thread.join();
}

既想要使用线程池来管理线程,又想要阻塞当前线程。结果运行时发现thread.join()方法并没有起作用,究其原因,thread线程并没有启动,然而确实有子线程运行并打印了数据,因此有必要了解一下submit()方法的执行原理。

ThreadPoolExecutor

ThreadPoolExecutor类图

从上图可以发现 ThreadPoolExecutor类相关的继承关系,而submit(Runnable)方法在其父类AbstractExecutorService中有具体实现:

public Future<?> submit(Runnable task) {
   
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
   
    return new FutureTask<T>(runnable, value);
}

从这里就能发现原有线程不启动的原因了,submit()方法接收一个Runnable参数对象,封装成FutureTask,并执行该任务,而不是启动原来的线程。

线程池处理任务的流程

ctl

线程池内部维护一个AtomicInteger类型的变量ctl,通过位运算的方式以该数字表示线程池的两个状态,原理为:二进制高 3 位表示 runState,低 29 位表示workerCount

  • workerCount:存活的线程数

  • runState:线程池当前的运行状态

    • RUNNING: 接受新任务,处理等待队列中的任务。
    • SHUTDOWN: 不接受新任务,处理等待队列中的任务。
    • STOP: 不接受新任务,丢弃等待队列中的任务,中断正在运行的任务。
    • TIDYING: 当所有的任务已终止,workCount 为0,线程池会变为 TIDYING 状态。接着会执行terminated()函数。
    • TERMINATEDterminated()函数执行完成。

execute()

线程池处理任务的主要方法为execute()方法,下面看一下它的源码:

public void execute(Runnable command) {
   
    if (command == null) throw new NullPointerException();
    int c = ctl.get();
    //1. 如果当前工作线程数小于 corePoolSize
    if (workerCountOf(c) < corePoolSize) {
   
        //创建核心线程,并将 command 作为其绑定运行的第一个任务
        if (addWorker(command, true))
            return;
        c = ctl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值