百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

JAVA线程池之一核心参数详解(java几种线程池)

wxin55 2024-11-07 13:13 15 浏览 0 评论

本章主要内容来源于

Java Threads(3rd Edition)(OReilly) author:Scott Oaks, Henry Wong

Java concurrent in practice author:Brian Goetz / Tim Peierls / Joshua Bloch / Joseph Bowbeer / David Holmes / Doug Lea

还有很多地方需要深入研究以及没有理解到位的地方,但是我会尽最大的努力做到知识全面化,为大家带来更详细,更深入的知识,如果有那些地方您觉得不对,希望可以在评论区指出,小编会感激不尽!!!

1. 线程池有那些好处

对于开发者来说,如果没有线程池我们需要创建大量的Thread,不论是开发者还是应用程序这都不是一个好的现象。而有了线程池我们只需要提交Runnable(Callable)这样的对象到线程池中,省去了对线程生命周期则的管理,并且实现了线程的复用。线程池中还维护了一个BlockingQueue,这样使得消费者和提供者可以分离,使开发者只需要关注业务逻辑即可,这样使得代码更加内聚,更加便于维护,当然这也只是解决了大部分问题,有时候线程池中提交任务的速度快于消费者处理业务的话,我们也需要拒绝新的任务到线程池,直到线程池中有空闲的位置,也有一些任务并不适用于线程池比如大文件的读取。

2. 线程池核心参数设置以及详解

接下来我们讨论下线程池的构造,线程池有很多构造函数,下面的构造函数是参数最齐的,已经覆盖所有构造函数的参数

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler);

}

首先说下各个参数含义:

coreSize 核心线程数

maximumPoolSize 最大线程数

keepAliveTime 线程存活时间

Unit 线程存活时间的时间单位比如秒,毫秒等

workQueue blockQueue是专门为高并发设计的容器

threadFactory 可以更线程默认的名字,状态,线程组,优先级策略

Handler 拒绝策略

总的来说线程池分为四个部分,分别是控制线程数量的coreSize,maximumPoolSize参数;控制队列的workQueue;控制线程存活时间keepAliveTime,unit和控制线程信息的threadFactory;最后是线程的拒绝策略handler,可以说线程池主要就是这四部分,除了构造函数之外ThreadPoolExecutor也提供了方法对核心参数进行修改,为了更进一步讨论,请看以下代码,在线程池中核心线程数设置为5,最大线程数为10,提交了110个任务


当我们创建线程池的时候,还没有提交任务到线程池,其实线程池中的是没有线程的,当提交了第一个任务,线程池则会创建一个线程,直到达到了核心线程数,这个时候如果核心线程数有空闲的新提交的任务会交给空闲的线程,如果没有空闲的线程则会提交到工作队列(BlockingQueue)中,如果Blockingqueue 如果已经满了,则创建新的线程,直到达到最大线程数,如果这个时候消费者处理速度还没有追上提供者,则会调用拒绝策略,拒绝新任务提交。所以本例中线程池一共可以容纳110个任务,工作队列容纳100个任务,核心线程处理5个,工作队列达到边界,创建新的线程到最大线程数.所以可能容乃110个任务,如果提交到第111个,线程池则会拒绝任务的提交。


还有就是工作队列(BlockingQueue)页影响着线程池的工作方式,上面例子中我们使用的是有界的LinkedBlockingQueue,java5开始提供了一系列的Blockingqueue有ArrayBlockingQueue,SynchronousQueue,LinkedBlockingQueue,PriorityBlockingQueue,DelayQueue等

SynchronousQueue:实际上并不是真正意义上的队列,SynchronousQueue更多的是在线程之间共享任务,工作队列的大小实际上是0,我们可以看到,当提交的任务超过11个时,由于消费者的处理能力追不上提供者,所以线程池拒绝了新的任务,因为使用SynchronousQueue处理任务的时候SynchronousQueue并不会排队,要么立即处理要么立即失败。



DelayQueue:延迟队列,实际上这个BlockingQueue并不适用于ThreadPoolExecutor,因为DelayQueue是延迟队列,而另一个线程池正是使用DelayQueue,才实现了定时调用的功能,这个线程池就是ScheduledThreadPoolExecutor


LinkedBlockingQueue:无边界队列:

注意LinkedBlockingQueue没有设置边界就是无限容量。在这种情况下,总是将任务添加到队列中成功,这意味着线程池不会创建超过M的线程和从不拒绝任务。

LinkedBlockingQueue(100),ArrayBlockingQueue,PriorityBlockingQueue有界队列:

假设队列P的界限。当任务被添加到池中时,它将创建线程,直到达到M个线程。此时,它开始将任务排队,直到等待的任务数达到P。随着添加更多任务,线程池开始添加线程,直到达到N个线程。如果N个线程处于活动状态,而P个任务处于队列中,则其他任务被拒绝。

PriorityBlockingQueue 是带有优先级的有界队列,默认大小为11个


那么我们应该如何设置这些参数呢?

如果线程数量过大则会在相对较小的CPU和内存中发生竞争,如果过小则会由很多空闲的CPU,导致吞吐量的不足。所以我们需要分析环境中有多少个CPU,内存是多大,是计算密集型的操作还是IO密集型的操作。对于计算密集型的任务,当前线程数量为CPU数量+1为最优。对于IO密集型或者有阻塞的任务,由于线程并不会一致执行,因此线程池应该过大,推荐的计算公式为

CPU利用率=CPU数量x目标CPU利用率x(1+(等待时长/计算时长))

CPU数量可以通过 Runtime.getRuntime().availableProcessors()获取


相关推荐

ES6中 Promise的使用场景?(es6promise用法例子)

一、介绍Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码doSomething(f...

JavaScript 对 Promise 并发的处理方法

Promise对象代表一个未来的值,它有三种状态:pending待定,这是Promise的初始状态,它可能成功,也可能失败,前途未卜fulfilled已完成,这是一种成功的状态,此时可以获取...

Promise的九大方法(promise的实例方法)

1、promise.resolv静态方法Promise.resolve(value)可以认为是newPromise方法的语法糖,比如Promise.resolve(42)可以认为是以下代码的语...

360前端一面~面试题解析(360前端开发面试题)

1.组件库按需加载怎么做的,具体打包配了什么-按需加载实现:借助打包工具(如Webpack的require.context或ES模块动态导入),在使用组件时才引入对应的代码。例如在V...

前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?

Promise的finally方法是一个非常有用的工具,它无论Promise是成功(fulfilled)还是失败(rejected)都会执行,且不改变Promise的最终结果。它的实现原...

最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式

看了全网手写Promise的,大部分对于新手还是比较难理解的,其中几个比较难的点:状态还未改变时通过发布订阅模式去收集事件实例化的时候通过调用构造函数里传出来的方法去修改类里面的状态,这个叫Re...

前端分享-Promise可以中途取消啦(promise可以取消吗)

传统Promise就像一台需要手动组装的设备,每次使用都要重新接线。而Promise.withResolvers的出现,相当于给开发者发了一个智能遥控器,可以随时随地控制异步操作。它解决了三大...

手写 Promise(手写输入法 中文)

前言都2020年了,Promise大家肯定都在用了,但是估计很多人对其原理还是一知半解,今天就让我们一起实现一个符合PromiseA+规范的Promise。附PromiseA+规范地址...

什么是 Promise.allSettled()!新手老手都要会?

Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的pr...

前端面试-关于Promise解析与高频面试题示范

Promise是啥,直接上图:Promise就是处理异步函数的API,它可以包裹一个异步函数,在异步函数完成时抛出完成状态,让代码结束远古时无限回掉的窘境。配合async/await语法糖,可...

宇宙厂:为什么前端离不开 Promise.withResolvers() ?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.为什么需要Promise.with...

Promise 新增了一个超实用的 API!

在JavaScript的世界里,Promise一直是处理异步操作的神器。而现在,随着ES2025的发布,Promise又迎来了一个超实用的新成员——Promise.try()!这个新方法简...

一次搞懂 Promise 异步处理(promise 异步顺序执行)

PromisePromise就像这个词的表面意识一样,表示一种承诺、许诺,会在后面给出一个结果,成功或者失败。现在已经成为了主流的异步编程的操作方式,写进了标准里面。状态Promise有且仅有...

Promise 核心机制详解(promise机制的实现原理)

一、Promise的核心状态机Promise本质上是一个状态机,其行为由内部状态严格管控。每个Promise实例在创建时处于Pending(等待)状态,此时异步操作尚未完成。当异步操作成功...

javascript——Promise(js实现promise)

1.PromiseES6开始支持,Promise对象用于一个异步操作的最终完成(包括成功和失败)及结果值的表示。简单说就是处理异步请求的。之所以叫Promise,就是我承诺,如果成功则怎么处理,失败怎...

取消回复欢迎 发表评论: