面试题:你分析过线程池源码吗?

本文深入探讨线程池的使用原因,详细解析JDK8中五种线程池的创建方式,包括固定大小线程池、工作窃取池、可缓存线程池、单线程池和定时线程池。同时,介绍了线程池的状态转换模型,帮助理解线程池的生命周期。

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

1.为什么要用线程池?

降低系统资源消耗

提高线程可控性

2.如何创建线程池?

JDK8中提供了5种创建线程池的方法

(1). newFixThreadPool

创建固定大小的线程池,可控制线程最大并发数,超过的线程会在队列中等待

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

(2).(JDK8新增)   newWorkStealingPool

会根据所需的并发数来动态创建和关闭线程,能够合理的使用CPU进行对任务进行并发操作,所以很适合使用在很耗时的任务上

public static ExecutorService newWorkStealingPool(int parallelism) {
    return new ForkJoinPool
        (parallelism,
         ForkJoinPool.defaultForkJoinWorkerThreadFactory,
         null, true);
}

这里返回的是一个ForkJoinPool对象

public ForkJoinPool(int parallelism,
                        ForkJoinWorkerThreadFactory factory,
                        UncaughtExceptionHandler handler,
                        boolean asyncMode) {
        this(checkParallelism(parallelism),
             checkFactory(factory),
             handler,
             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
             "ForkJoinPool-" + nextPoolId() + "-worker-");
        checkPermission();
    }

使用一个无限队列来保存需要执行的任务,可以传入线程的数量,不传入的话,默认使用当前计算机中可以使用的CPU数量,使用分治法来解决问题,使用fork()和join()来进行调用

(3).newCashedThreadPool

创建一个可缓存的线程池,可以灵活回收空闲线程,如果无法回收,则新建线程

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

(4).newSingleThreadPoolExecutor

创建一个单线程的线程池

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

(5).newScheduledThreadPool

创建一个定长线程池,支持定时以及周期性任务执行

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

3.源码结构(Executor框架结构)

从上往下依次是:

Executor

一个运行新任务的简单接口

ExecutorService

扩展了Executor接口,添加了一些用来管理执行器生命周期和任务生命周期的方法

AbstractExecutorService

对ExecutorService接口的抽象类实现

ThreadPoolExecutor

Java线程池的核心实现

4.线程池状态的转换模型

running:

线程池一旦被创建,就处于running状态,能够接收新任务,以及对已添加的任务进行处理

shutdown:

不能接收新任务,但能够处理已添加的任务

stop:

不接受新任务,不处理已添加的任务,并且会中断正在处理的任务

tidying:

当所有的任务已经终止,线程池就会变成tidying状态

terminated:

线程池彻底终止,就会变成terminated状态

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值