【Java基础】线程池

如何创建线程池?

《阿里巴巴 Java 开发手册》中强制线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让开发者更加明确线程池的运行规则,规避资源耗尽的⻛险。

FixedThreadPool

返回一个固定线程数量的线程池。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中, 待有线程空闲时,便处理在任务队列中的任务。允许请求的队列⻓度为Integer.MAX_VALUE,可能堆积大量的请求导致 OOM。

CachedThreadPool:

返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。允许创建的线程数量为 。

ThreadPoolExecutor 的参数:

  • corePoolSize : 核心线程数定义了最小可以同时运行的线程数量。
  • maximumPoolSize : 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
  • workQueue: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到,新任务就会被存放在队列中。

ThreadPoolExecutor其他参数:

  • keepAliveTime:当线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁
  • handler :饱和策略。如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,
    ThreadPoolTaskExecutor 定义一些策略:
      • Abort: 抛出 RejectedExecutionException来拒绝新任务的处理。
      • CallerRuns: 调用执行自己的线程运行任务,也就是直接在调用execute方法的线程中运行被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。
      • Discard: 不处理新任务,直接丢弃掉。
      • DiscardOldest: 此策略将丢弃最早的未处理的任务请求。

线程池大小设置

  CPU 密集型任务(N+1)

     这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺⻚中断,或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来 的一个线程就可以充分利用 CPU 的空闲时间。

  I/O 密集型任务(2N)

    这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内不会占用CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中, 我们可以多配置一些线程,具体的计算方法是 2N。

  如何判断是 CPU 密集任务还是 IO 密集任务?

    CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内存中对大量数据进行排序。但凡涉及到网络读取,文件读取这类都是 IO 密集型,这类任务的特点是 CPU 计算耗费时间相比于等待 IO 操作完成的时间来说很少,大部分时间都花在了等待 IO 操作完成上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值