CPU密集型和IO密集型

CPU密集型(CPU-bound)和IO密集型(IO-bound)是两种常见的计算密集型和IO操作密集型任务类型

1. CPU密集型任务:

  • CPU密集型任务是指在执行过程中主要依赖于CPU处理能力的任务。
  • 这类任务通常涉及大量的计算、逻辑判断、数据处理等操作。
  • 例如,科学计算、图像处理、加密解密等任务都属于CPU密集型任务。
  • 在CPU密集型任务中,CPU的处理能力是主要瓶颈,而IO操作相对较少。

2. IO密集型任务:

  • IO密集型任务是指在执行过程中主要依赖于IO操作(如磁盘读写、网络通信)的任务。
  • 这类任务通常涉及大量的读取和写入操作,而CPU的计算需求相对较少。
  • 例如,文件操作、数据库查询、网络爬虫等任务都属于IO密集型任务。
  • 在IO密集型任务中,IO操作的速度和效率是主要瓶颈,而CPU的处理能力往往有闲置。

针对不同类型的任务,可以采取不同的优化策略:

  • 对于CPU密集型任务,可以考虑优化算法、并行计算、利用多核CPU等方式来提高计算性能。
  • 对于IO密集型任务,可以考虑使用异步IO、多线程或多进程并发处理、缓存技术等方式来提高IO操作的效率。

在实际应用中,任务的类型决定了对系统资源的需求和瓶颈,针对不同类型的任务进行合理的优化和资源分配,可以提高系统的性能和响应能力。

如何确定线程池大小?

线程数不是越多越好。

由于CPU的核心数有限,线程之间切换也需要开销,频繁的切换上下文会使性能降低,适得其反。

简单的总结就是:

Ncpu 表示 核心数。

如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 Ncpu+1

如果是IO密集型任务,参考值可以设置为 2 * Ncpu

上面两个公式为什么是Ncpu+1 呢,而不是Ncpu+2 呢,为什么不是3 * Ncpu 呢?

在《Java并发编程实践》中,是这样来计算线程池的线程数目的:

一个基准负载下,使用 几种不同大小的线程池运行你的应用程序,并观察CPU利用率的水平。 给定下列定义:

Ncpu = CPU的数量 Ucpu = 目标CPU的使用率, 0 <= Ucpu <= 1 W/C = 等待时间与计算时间的比率

为保持处理器达到期望的使用率,最优的池的大小等于:

Nthreads = Ncpu x Ucpu x (1 + W/C)

线程数 = CPU 核心数 / (1 - 阻塞系数)

其中计算密集型阻塞系数为 0,IO 密集型阻塞系数接近 1,一般认为在 0.8 ~ 0.9 之间。比如 8 核 CPU,按照公式就是 2 / ( 1 - 0.9 ) = 20 个线程数

**

线程池的核心参数

**
1.corePoolSize:the number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set

(核心线程数大小:不管它们创建以后是不是空闲的。线程池需要保持 corePoolSize 数量的线程,除非设置了 allowCoreThreadTimeOut。)

2.maximumPoolSize:the maximum number of threads to allow in the pool。

(最大线程数:线程池中最多允许创建 maximumPoolSize 个线程。)

3.keepAliveTime:when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating。

(存活时间:如果经过 keepAliveTime 时间后,超过核心线程数的线程还没有接受到新的任务,那就回收。)

4.unit:the time unit for the {@code keepAliveTime} argument

(keepAliveTime 的时间单位。)

5.workQueue:the queue to use for holding tasks before they are executed. This queue will hold only the {@code Runnable} tasks submitted by the {@code execute} method。

(存放待执行任务的队列:当提交的任务数超过核心线程数大小后,再提交的任务就存放在这里。它仅仅用来存放被 execute 方法提交的 Runnable 任务。所以这里就不要翻译为工作队列了,好吗?不要自己给自己挖坑。)

6.threadFactory:the factory to use when the executor creates a new thread。

(线程工程:用来创建线程工厂。比如这里面可以自定义线程名称,当进行虚拟机栈分析时,看着名字就知道这个线程是哪里来的,不会懵逼。)

7.handler :the handler to use when execution is blocked because the thread bounds and queue capacities are reached。

(拒绝策略:当队列里面放满了任务、最大线程数的线程都在工作时,这时继续提交的任务线程池就处理不了,应该执行怎么样的拒绝策略。)

**

线程池拒绝策略

**

这几种策略模式都实现了RejectedExecutionHandler 接口。

AbortPolicy 丢弃任务,抛运行时异常。
CallerRunsPolicy 执行任务。
DiscardPolicy 忽视,什么都不会发生。
DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务。

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

会说话的皮卡丘

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值