四种常见线程池的原理,你学会了吗?
创始人
2025-07-05 02:51:09
0

newFixedThreadPool (固定数目线程的线程池)

newCachedThreadPool (可缓存线程的线程池)

newSingleThreadExecutor (单线程的线程池)

newScheduledThreadPool (定时及周期执行的线程池)

前三种线程池的构造直接调用ThreadPoolExecutor的构造方法。

newSingleThreadExecutor

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

线程池特点:

核心线程数:1

最大线程数:1

阻塞队列是无界队列LinkedBlockingQueue,可能会导致OOM

keepAliveTime:0

工作流程:

1、提交任务

2、线程池是否有一条线程在,如果没有,新建线程执行任务

3、如果有,将任务加到阻塞队列

4、当前的唯一线程,从队列取任务,执行完一个,再继续,一个线程执行任务

适用场景:

适用于串行执行任务的场景,一个任务一个任务地执行

newFixedThreadPool

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

线程池特点:

核心线程数和最大线程数大小一样;

没有所谓的非空闲时间,即keepAliveTime为0;

阻塞队列为无界队列LinkedBlockingQueue,可能会导致OOM;


工作流程:

1、提交任务;

2、如果线程数少于核心线程,创建核心线程执行任务;

3、如果线程数等于核心线程,把任务添加到LinkedBlockingQueue阻塞队列;

4、如果线程执行完任务,去阻塞队列取任务,继续执行。

适用场景:

FixedThreadPool适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能少的分配线程,即适用执行长期的任务。

newCachedThreadPool

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

线程池特点:

核心线程数为0;

最大线程数为Integer.MAX_VALUE,即无限大,可能会因为无线创建线程,导致OOM

阻塞队列是SynchronousQueue

非核心线程空闲存活时间为60s

当提交任务速度大于处理任务的速度时,每次提交一个任务,就必然会创建一个线程。

极端情况下会创建过多的线程,耗尽CPU和内存资源。由于空闲60秒的线程会被终止,长时间保持空闲的CachedThreadPool不会占用任何资源。


工作流程:

提交任务;

因为没有核心线程,所以任务会直接加到SynchronousQueue队列;

判断是否有空闲线程,如果有,就去取出任务执行;

如果没有空闲线程,就新建一个线程执行;

执行完任务的线程,还可以存活60s,如果在这期间接到任务,就可以继续活下去,否则被销毁。

适用场景:

用于并发执行大量短期的小任务。

newScheduleThreadPool

public ScheduledThreadPoolExecutor(int corePoolSize) {
  super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}

线程池特点:

最大线程数为Integer.MAX_VALUE,也有OOM风险

阻塞队列是DelayedWorkQueue

keepAliveTime为0

scheduleAtFixedRate():按某种速率周期执行

scheduleWithFixedDelay():在某个延迟后执行

工作机制:

线程从DelayQueue中获取已到期的ScheduledFutureTask(DelayQueue.take())。到期任务是指ScheduledFutureTask的time大于等于当前时间。

线程执行这个ScheduleFutureTask

线程修改ScheduledFutureTask的time变量为下次将要被执行的时间

线程把这个修改time之后的ScheduledFutureTask放回DelayQueue中(DelayQueue.add())。


使用场景:

周期性执行任务的场景,需要限制线程数量的场景。

使用无界队列的线程池会导致什么问题:

例如newFixedThreadPool使用了无界的阻塞队列LinkedBlockingQueue,如果线程获取一个任务后,任务的执行时间比较长,会导致队列的任务越积越多,导致机器内存使用不停飙升,最终导致OOM。

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...