常见四种线程池

目录

FixedThreadPool

CachedThreadPool

ScheduledThreadPool()

SingleThreadExecutor

本节我们来详解一下Executor框架的成员中的ThreadPoolExecutor

ThreadPoolExecutor 通常使用工厂 类 Executors 来 创 建。 Executors 可以 创 建 3 种 类 型的
ThreadPoolExecutor:SingleThreadExecutor、FixedThreadPool和CachedThreadPool。

本节就是详解这些类型的ThreadPoolExecutor

对Executor框架的了解可以看博主的上一篇文:
https://blog.csdn.net/m0_60264772/article/details/122778045

FixedThreadPool

特点:

  • 核心线程数 == 最大线程数(没有救急线程),自然也无需超时时间
  • 阻塞队列是无界的,可以放任意数量的任务
  • 适用于任务量已知,相对耗时的任务
public static ExecutorService newFixedThreadPool(int threads) {
    return new ThreadPoolExecutor(threads,threads,
            0L, TimeUnit.MICROSECONDS,
            new LinkedBlockingDeque<Runnable>());
}

CachedThreadPool

特点:

  • 核心线程数是0,最大线程数是Integer.MAX_VALUE,救急线程的空闲时间为60s,意味着:
    • 全部都是救急线程(60s后回收)
    • 救急线程可以无限创建
  • 队列采用了SynchronousQueue实现特点是,它没有容量,没有线程来取是放不进去的(一手交钱,一手交货)
  • 整个线程线程数会根据任务量不断增长,没有上限,任务执行完毕,60s后释放线程
  • 适合任务数比较密集,但每个任务执行时间较短的情况
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0,
                Integer.MAX_VALUE,
                60L,
                TimeUnit.SECONDS,
                new SynchronousQueue<>());
    }

ScheduledThreadPool()

定长线程池:

  1. 支持定时及周期性任务执行
  2. ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);
     
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
     
    //ScheduledThreadPoolExecutor():
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }

SingleThreadExecutor

特点:

  • 线程数始终为1,不能修改。希望多个任务排队执行。任务数多于 1 时,会放入无界队列排队。 任务执行完毕,这唯一的线程也不会被释放
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

有同学可能就会有疑问了,那么new FixedThreadPool(1)参数设置为1不是就一样了吗,实际上还是有区别的:

  • 自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而newSingleThreadExecutor线程池还会新建一个线程,保证池的正常工作
  • Executors.newSingleThreadExecutor() 线程个数始终为1,不能修改(FinalizableDelegatedExecutorService 应用的是装饰器模式,只对外暴露了    ExecutorService 接口,因此不能调用 ThreadPoolExecutor 中特有的方法)
  • 和Executors.newFixedThreadPool(1) 初始时为1时的区别:Executors.newFixedThreadPool(1) 初始时为1,以后还可以修改,对外暴露的是 ThreadPoolExecutor 对象,可以强转后调用 setCorePoolSize 等方法进行修改
     

Executors 返回线程池对象的弊端如下

FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为 Integer.MAX_VALUE (无界阻塞队列),可能堆积大量的请求,从而导致 OOM。
CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。

建议使用ThreadPoolExecutor来创建线程

避免上面的措施 : 使用有界队列,控制线程创建数量

除了避免 OOM 的原因之外,不推荐使用 Executors提供的两种快捷的线程池的原因还有:

实际使用中需要根据自己机器的性能、业务场景来手动配置线程池的参数比如核心线程数、使用的任务队列、饱和策略等等。
我们应该显示地给我们的线程池命名,这样有助于我们定位问题。
 

  • 11
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值