当前位置: 首页 > news >正文

莞城网站建设wordpress点击文章跳转外站

莞城网站建设,wordpress点击文章跳转外站,一键制作单页网站,标签怎么删除wordpress随着计算机行业的飞速发展#xff0c;摩尔定律逐渐失效#xff0c;多核CPU成为主流。使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器。J.U.C提供的线程池#xff1a;ThreadPoolExecutor类#xff0c;帮助开发人员管理线程并方便地执行并行任务。了解并合理使… 随着计算机行业的飞速发展摩尔定律逐渐失效多核CPU成为主流。使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器。J.U.C提供的线程池ThreadPoolExecutor类帮助开发人员管理线程并方便地执行并行任务。了解并合理使用线程池是一个开发人员必修的基本功。 本文开篇简述线程池概念和用途接着结合线程池的源码帮助读者领略线程池的设计思路最后回归实践通过案例讲述使用线程池遇到的问题并给出了一种动态化线程池解决方案。 一、写在前面 1.1 线程池是什么 线程池Thread Pool是一种基于池化思想管理线程的工具经常出现在多线程服务器中如MySQL。 线程过多会带来额外的开销其中包括创建销毁线程的开销、调度线程的开销等等同时也降低了计算机的整体性能。线程池维护多个线程等待监督管理者分配可并发执行的任务。这种做法一方面避免了处理任务时创建销毁线程开销的代价另一方面避免了线程数量膨胀导致的过分调度问题保证了对内核的充分利用。 而本文描述线程池是JDK中提供的ThreadPoolExecutor类。 当然使用线程池可以带来一系列好处 降低资源消耗通过池化技术重复利用已创建的线程降低线程创建和销毁造成的损耗。提高响应速度任务到达时无需等待线程创建即可立即执行。提高线程的可管理性线程是稀缺资源如果无限制创建不仅会消耗系统资源还会因为线程的不合理分布导致资源调度失衡降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。提供更多更强大的功能线程池具备可拓展性允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor就允许任务延期执行或定期执行。1.2 线程池解决的问题是什么 线程池解决的核心问题就是资源管理问题。在并发环境下系统不能够确定在任意时刻中有多少任务需要执行有多少资源需要投入。这种不确定性将带来以下若干问题 频繁申请/销毁资源和调度资源将带来额外的消耗可能会非常巨大。对资源无限申请缺少抑制手段易引发系统资源耗尽的风险。系统无法合理管理内部的资源分布会降低系统的稳定性。为解决资源分配这个问题线程池采用了“池化”Pooling思想。池化顾名思义是为了最大化收益并最小化风险而将资源统一在一起管理的一种思想。 Pooling is the grouping together of resources (assets, equipment, personnel, effort, etc.) for the purposes of maximizing advantage or minimizing risk to the users. The term is used in finance, computing and equipment management.——wikipedia “池化”思想不仅仅能应用在计算机领域在金融、设备、人员管理、工作管理等领域也有相关的应用。 在计算机领域中的表现为统一管理IT资源包括服务器、存储、和网络资源等等。通过共享资源使用户在低投入中获益。除去线程池还有其他比较典型的几种使用策略包括 内存池(Memory Pooling)预先申请内存提升申请内存速度减少内存碎片。连接池(Connection Pooling)预先申请数据库连接提升申请连接的速度降低系统的开销。实例池(Object Pooling)循环使用对象减少资源在初始化和释放时的昂贵损耗。在了解完“是什么”和“为什么”之后下面我们来一起深入一下线程池的内部实现原理。 二、线程池核心设计与实现 在前文中我们了解到线程池是一种通过“池化”思想帮助我们管理线程而获取并发性的工具在Java中的体现是ThreadPoolExecutor类。那么它的的详细设计与实现是什么样的呢我们会在本章进行详细介绍。 2.1 总体设计 Java中的线程池核心实现类是ThreadPoolExecutor本章基于JDK 1.8的源码来分析Java线程池的核心设计与实现。我们首先来看一下ThreadPoolExecutor的UML类图了解下ThreadPoolExecutor的继承关系。 ThreadPoolExecutor实现的顶层接口是Executor顶层接口Executor提供了一种思想将任务提交和任务执行进行解耦。用户无需关注如何创建线程如何调度线程来执行任务用户只需提供Runnable对象将任务的运行逻辑提交到执行器(Executor)中由Executor框架完成线程的调配和任务的执行部分。ExecutorService接口增加了一些能力1扩充执行任务的能力补充可以为一个或一批异步任务生成Future的方法2提供了管控线程池的方法比如停止线程池的运行。AbstractExecutorService则是上层的抽象类将执行任务的流程串联了起来保证下层的实现只需关注一个执行任务的方法即可。最下层的实现类ThreadPoolExecutor实现最复杂的运行部分ThreadPoolExecutor将会一方面维护自身的生命周期另一方面同时管理线程和任务使两者良好的结合从而执行并行任务。 ThreadPoolExecutor是如何运行如何同时维护线程和执行任务的呢其运行机制如下图所示 线程池在内部实际上构建了一个生产者消费者模型将线程和任务两者解耦并不直接关联从而良好的缓冲任务复用线程。线程池的运行主要分成两部分任务管理、线程管理。任务管理部分充当生产者的角色当任务提交后线程池会判断该任务后续的流转1直接申请线程执行该任务2缓冲到队列中等待线程执行3拒绝该任务。线程管理部分是消费者它们被统一维护在线程池内根据任务请求进行线程的分配当线程执行完任务后则会继续获取新的任务去执行最终当线程获取不到任务的时候线程就会被回收。 接下来我们会按照以下三个部分去详细讲解线程池运行机制 线程池如何维护自身状态。线程池如何管理任务。线程池如何管理线程。2.2 生命周期管理 线程池运行的状态并不是用户显式设置的而是伴随着线程池的运行由内部来维护。线程池内部使用一个变量维护两个值运行状态(runState)和线程数量 (workerCount)。在具体实现中线程池将运行状态(runState)、线程数量 (workerCount)两个关键参数的维护放在了一起如下代码所示 private final AtomicInteger ctl new AtomicInteger(ctlOf(RUNNING, 0));ctl这个AtomicInteger类型是对线程池的运行状态和线程池中有效线程的数量进行控制的一个字段 它同时包含两部分的信息线程池的运行状态 (runState) 和线程池内有效线程的数量 (workerCount)高3位保存runState低29位保存workerCount两个变量之间互不干扰。用一个变量去存储两个值可避免在做相关决策时出现不一致的情况不必为了维护两者的一致而占用锁资源。通过阅读线程池源代码也可以发现经常出现要同时判断线程池运行状态和线程数量的情况。线程池也提供了若干方法去供用户获得线程池当前的运行状态、线程个数。这里都使用的是位运算的方式相比于基本运算速度也会快很多。 关于内部封装的获取生命周期状态、获取线程池线程数量的计算方法如以下代码所示 private static int runStateOf(int c) { return c ~CAPACITY; } //计算当前运行状态 private static int workerCountOf(int c) { return c CAPACITY; } //计算当前线程数量 private static int ctlOf(int rs, int wc) { return rs | wc; } //通过状态和线程数生成ctlThreadPoolExecutor的运行状态有5种分别为 其生命周期转换如下入所示 2.3 任务执行机制 2.3.1 任务调度 任务调度是线程池的主要入口当用户提交了一个任务接下来这个任务将如何执行都是由这个阶段决定的。了解这部分就相当于了解了线程池的核心运行机制。 首先所有任务的调度都是由execute方法完成的这部分完成的工作是检查现在线程池的运行状态、运行线程数、运行策略决定接下来执行的流程是直接申请线程执行或是缓冲到队列中执行亦或是直接拒绝该任务。其执行过程如下 首先检测线程池运行状态如果不是RUNNING则直接拒绝线程池要保证在RUNNING的状态下执行任务。如果workerCount corePoolSize则创建并启动一个线程来执行新提交的任务。如果workerCount corePoolSize且线程池内的阻塞队列未满则将任务添加到该阻塞队列中。如果workerCount corePoolSize workerCount maximumPoolSize且线程池内的阻塞队列已满则创建并启动一个线程来执行新提交的任务。如果workerCount maximumPoolSize并且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。其执行流程如下图所示 2.3.2 任务缓冲 任务缓冲模块是线程池能够管理任务的核心部分。线程池的本质是对任务和线程的管理而做到这一点最关键的思想就是将任务和线程两者解耦不让两者直接关联才可以做后续的分配工作。线程池中是以生产者消费者模式通过一个阻塞队列来实现的。阻塞队列缓存任务工作线程从阻塞队列中获取任务。 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是在队列为空时获取元素的线程会等待队列变为非空。当队列满时存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景生产者是往队列里添加元素的线程消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器而消费者也只从容器里拿元素。 下图中展示了线程1往阻塞队列中添加元素而线程2从阻塞队列中移除元素 使用不同的队列可以实现不一样的任务存取策略。在这里我们可以再介绍下阻塞队列的成员 2.3.3 任务申请 由上文的任务分配部分可知任务的执行有两种可能一种是任务直接由新创建的线程执行。另一种是线程从任务队列中获取任务然后执行执行完任务的空闲线程会再次去从队列中申请任务再去执行。第一种情况仅出现在线程初始创建的时候第二种是线程获取任务绝大多数的情况。 线程需要从任务缓存模块中不断地取任务执行帮助线程从阻塞队列中获取任务实现线程管理模块和任务管理模块之间的通信。这部分策略由getTask方法实现其执行流程如下图所示 getTask这部分进行了多次判断为的是控制线程的数量使其符合线程池的状态。如果线程池现在不应该持有那么多线程则会返回null值。工作线程Worker会不断接收新任务去执行而当工作线程Worker接收不到任务的时候就会开始被回收。 2.3.4 任务拒绝 任务拒绝模块是线程池的保护部分线程池有一个最大的容量当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时就需要拒绝掉该任务采取任务拒绝策略保护线程池。 拒绝策略是一个接口其设计如下 public interface RejectedExecutionHandler {void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }用户可以通过实现这个接口去定制拒绝策略也可以选择JDK提供的四种已有拒绝策略其特点如下 2.4 Worker线程管理 2.4.1 Worker线程 线程池为了掌握线程的状态并维护线程的生命周期设计了线程池内的工作线程Worker。我们来看一下它的部分代码 private final class Worker extends AbstractQueuedSynchronizer implements Runnable{final Thread thread;//Worker持有的线程Runnable firstTask;//初始化的任务可以为null }Worker这个工作线程实现了Runnable接口并持有一个线程thread一个初始化的任务firstTask。thread是在调用构造方法时通过ThreadFactory来创建的线程可以用来执行任务firstTask用它来保存传入的第一个任务这个任务可以有也可以为null。如果这个值是非空的那么线程就会在启动初期立即执行这个任务也就对应核心线程创建时的情况如果这个值是null那么就需要创建一个线程去执行任务列表workQueue中的任务也就是非核心线程的创建。 Worker执行任务的模型如下图所示 线程池需要管理线程的生命周期需要在线程长时间不运行的时候进行回收。线程池使用一张Hash表去持有线程的引用这样可以通过添加引用、移除引用这样的操作来控制线程的生命周期。这个时候重要的就是如何判断线程是否在运行。 ​Worker是通过继承AQS使用AQS来实现独占锁这个功能。没有使用可重入锁ReentrantLock而是使用AQS为的就是实现不可重入的特性去反应线程现在的执行状态。 1.lock方法一旦获取了独占锁表示当前线程正在执行任务中。 2.如果正在执行任务则不应该中断线程。 3.如果该线程现在不是独占锁的状态也就是空闲的状态说明它没有在处理任务这时可以对该线程进行中断。 4.线程池在执行shutdown方法或tryTerminate方法时会调用interruptIdleWorkers方法来中断空闲的线程interruptIdleWorkers方法会使用tryLock方法来判断线程池中的线程是否是空闲状态如果线程是空闲状态则可以安全回收。 在线程回收过程中就使用到了这种特性回收过程如下图所示 2.4.2 Worker线程增加 增加线程是通过线程池中的addWorker方法该方法的功能就是增加一个线程该方法不考虑线程池是在哪个阶段增加的该线程这个分配线程的策略是在上个步骤完成的该步骤仅仅完成增加线程并使它运行最后返回是否成功这个结果。addWorker方法有两个参数firstTask、core。firstTask参数用于指定新增的线程执行的第一个任务该参数可以为空core参数为true表示在新增线程时会判断当前活动线程数是否少于corePoolSizefalse表示新增线程前需要判断当前活动线程数是否少于maximumPoolSize其执行流程如下图所示 2.4.3 Worker线程回收 线程池中线程的销毁依赖JVM自动的回收线程池做的工作是根据当前线程池的状态维护一定数量的线程引用防止这部分线程被JVM回收当线程池决定哪些线程需要回收时只需要将其引用消除即可。Worker被创建出来后就会不断地进行轮询然后获取任务去执行核心线程可以无限等待获取任务非核心线程要限时获取任务。当Worker无法获取到任务也就是获取的任务为空时循环会结束Worker会主动消除自身在线程池内的引用。 try {while (task ! null || (task getTask()) ! null) {//执行任务} } finally {processWorkerExit(w, completedAbruptly);//获取不到任务时主动回收自己 }线程回收的工作是在processWorkerExit方法完成的。 事实上在这个方法中将线程引用移出线程池就已经结束了线程销毁的部分。但由于引起线程销毁的可能性有很多线程池还要判断是什么引发了这次销毁是否要改变线程池的现阶段状态是否要根据新状态重新分配线程。 2.4.4 Worker线程执行任务 在Worker类中的run方法调用了runWorker方法来执行任务runWorker方法的执行过程如下 1.while循环不断地通过getTask()方法获取任务。 2.getTask()方法从阻塞队列中取任务。 3.如果线程池正在停止那么要保证当前线程是中断状态否则要保证当前线程不是中断状态。 4.执行任务。 5.如果getTask结果为null则跳出循环执行processWorkerExit()方法销毁线程。 执行流程如下图所示 三、线程池在业务中的实践 3.1 业务背景 在当今的互联网业界为了最大程度利用CPU的多核性能并行运算的能力是不可或缺的。通过线程池管理线程获取并发性是一个非常基础的操作让我们来看两个典型的使用线程池获取并发性的场景。 场景1快速响应用户请求 描述用户发起的实时请求服务追求响应时间。比如说用户要查看一个商品的信息那么我们需要将商品维度的一系列信息如商品的价格、优惠、库存、图片等等聚合起来展示给用户。 分析从用户体验角度看这个结果响应的越快越好如果一个页面半天都刷不出用户可能就放弃查看这个商品了。而面向用户的功能聚合通常非常复杂伴随着调用与调用之间的级联、多级级联等情况业务开发同学往往会选择使用线程池这种简单的方式将调用封装成任务并行的执行缩短总体响应时间。另外使用线程池也是有考量的这种场景最重要的就是获取最大的响应速度去满足用户所以应该不设置队列去缓冲并发任务调高corePoolSize和maxPoolSize去尽可能创造多的线程快速执行任务。 场景2快速处理批量任务 描述离线的大量计算任务需要快速执行。比如说统计某个报表需要计算出全国各个门店中有哪些商品有某种属性用于后续营销策略的分析那么我们需要查询全国所有门店中的所有商品并且记录具有某属性的商品然后快速生成报表。 分析这种场景需要执行大量的任务我们也会希望任务执行的越快越好。这种情况下也应该使用多线程策略并行计算。但与响应速度优先的场景区别在于这类场景任务量巨大并不需要瞬时的完成而是关注如何使用有限的资源尽可能在单位时间内处理更多的任务也就是吞吐量优先的问题。所以应该设置队列去缓冲并发任务调整合适的corePoolSize去设置处理任务的线程数。在这里设置的线程数过多可能还会引发线程上下文切换频繁的问题也会降低处理任务的速度降低吞吐量。 3.2 实际问题及方案思考 线程池使用面临的核心的问题在于线程池的参数并不好配置。一方面线程池的运行机制不是很好理解配置合理需要强依赖开发人员的个人经验和知识另一方面线程池执行的情况和任务类型相关性较大IO密集型和CPU密集型的任务运行起来的情况差异非常大这导致业界并没有一些成熟的经验策略帮助开发人员参考。 关于线程池配置不合理引发的故障公司内部有较多记录下面举一些例子 Case12018年XX页面展示接口大量调用降级 事故描述XX页面展示接口产生大量调用降级数量级在几十到上百。 事故原因该服务展示接口内部逻辑使用线程池做并行计算由于没有预估好调用的流量导致最大核心数设置偏小大量抛出RejectedExecutionException触发接口降级条件示意图如下 Case22018年XX业务服务不可用S2级故障 事故描述XX业务提供的服务执行时间过长作为上游服务整体超时大量下游服务调用失败。 事故原因该服务处理请求内部逻辑使用线程池做资源隔离由于队列设置过长最大线程数设置失效导致请求数量增加时大量任务堆积在队列中任务执行时间过长最终导致下游服务的大量调用超时失败。示意图如下 业务中要使用线程池而使用不当又会导致故障那么我们怎样才能更好地使用线程池呢针对这个问题我们下面延展几个方向 1. 能否不用线程池? 回到最初的问题业务使用线程池是为了获取并发性对于获取并发性是否可以有什么其他的方案呢替代我们尝试进行了一些其他方案的调研 综合考虑这些新的方案都能在某种情况下提升并行任务的性能然而本次重点解决的问题是如何更简易、更安全地获得的并发性。另外Actor模型的应用实际上甚少只在Scala中使用广泛协程框架在Java中维护的也不成熟。这三者现阶段都不是足够的易用也并不能解决业务上现阶段的问题。 2. 追求参数设置合理性 有没有一种计算公式能够让开发同学很简易地计算出某种场景中的线程池应该是什么参数呢 带着这样的疑问我们调研了业界的一些线程池参数配置方案 调研了以上业界方案后我们并没有得出通用的线程池计算方式。并发任务的执行情况和任务类型相关IO密集型和CPU密集型的任务运行起来的情况差异非常大但这种占比是较难合理预估的这导致很难有一个简单有效的通用公式帮我们直接计算出结果。 3. 线程池参数动态化 尽管经过谨慎的评估仍然不能够保证一次计算出来合适的参数那么我们是否可以将修改线程池参数的成本降下来这样至少可以发生故障的时候可以快速调整从而缩短故障恢复的时间呢基于这个思考我们是否可以将线程池的参数从代码中迁移到分布式配置中心上实现线程池参数可动态配置和即时生效线程池参数动态化前后的参数修改流程对比如下 基于以上三个方向对比我们可以看出参数动态化方向简单有效。 3.3 动态化线程池 3.3.1 整体设计 动态化线程池的核心设计包括以下三个方面 简化线程池配置线程池构造参数有8个但是最核心的是3个corePoolSize、maximumPoolSizeworkQueue它们最大程度地决定了线程池的任务分配和线程分配策略。考虑到在实际应用中我们获取并发性的场景主要是两种1并行执行子任务提高响应速度。这种情况下应该使用同步队列没有什么任务应该被缓存下来而是应该立即执行。2并行执行大批次任务提升吞吐量。这种情况下应该使用有界队列使用队列去缓冲大批量的任务队列容量必须声明防止任务无限制堆积。所以线程池只需要提供这三个关键参数的配置并且提供两种队列的选择就可以满足绝大多数的业务需求Less is More。参数可动态修改为了解决参数不好配修改参数成本高等问题。在Java线程池留有高扩展性的基础上封装线程池允许线程池监听同步外部的消息根据消息进行修改配置。将线程池的配置放置在平台侧允许开发同学简单的查看、修改线程池配置。增加线程池监控对某事物缺乏状态的观测就对其改进无从下手。在线程池执行任务的生命周期添加监控能力帮助开发同学了解线程池状态。 3.3.2 功能架构 动态化线程池提供如下功能 动态调参支持线程池参数动态调整、界面化操作包括修改线程池核心大小、最大核心大小、队列长度等参数修改后及时生效。 任务监控支持应用粒度、线程池粒度、任务粒度的Transaction监控可以看到线程池的任务执行情况、最大任务执行时间、平均任务执行时间、95/99线等。 负载告警线程池队列任务积压到一定值的时候会通过大象美团内部通讯工具告知应用开发负责人当线程池负载数达到一定阈值的时候会通过大象告知应用开发负责人。 操作监控创建/修改和删除线程池都会通知到应用的开发负责人。 操作日志可以查看线程池参数的修改记录谁在什么时候修改了线程池参数、修改前的参数值是什么。 权限校验只有应用开发负责人才能够修改应用的线程池参数。 参数动态化 JDK原生线程池ThreadPoolExecutor提供了如下几个public的setter方法如下图所示 JDK允许线程池使用方通过ThreadPoolExecutor的实例来动态设置线程池的核心策略以setCorePoolSize为方法例在运行期线程池使用方调用此方法设置corePoolSize之后线程池会直接覆盖原来的corePoolSize值并且基于当前值和原始值的比较结果采取不同的处理策略。对于当前值小于当前工作线程数的情况说明有多余的worker线程此时会向当前idle的worker线程发起中断请求以实现回收多余的worker在下次idel的时候也会被回收对于当前值大于原始值且当前队列中有待执行任务则线程池会创建新的worker线程来执行队列任务setCorePoolSize具体流程如下 线程池内部会处理好当前状态做到平滑修改其他几个方法限于篇幅这里不一一介绍。重点是基于这几个public方法我们只需要维护ThreadPoolExecutor的实例并且在需要修改的时候拿到实例修改其参数即可。基于以上的思路我们实现了线程池参数的动态化、线程池参数在管理平台可配置可修改其效果图如下图所示 用户可以在管理平台上通过线程池的名字找到指定的线程池然后对其参数进行修改保存后会实时生效。目前支持的动态参数包括核心数、最大值、队列长度等。除此之外在界面中我们还能看到用户可以配置是否开启告警、队列等待任务告警阈值、活跃度告警等等。关于监控和告警我们下面一节会对齐进行介绍。 线程池监控 除了参数动态化之外为了更好地使用线程池我们需要对线程池的运行状况有感知比如当前线程池的负载是怎么样的分配的资源够不够用任务的执行情况是怎么样的是长任务还是短任务基于对这些问题的思考动态化线程池提供了多个维度的监控和告警能力包括线程池活跃度、任务的执行Transaction频率、耗时、Reject异常、线程池内部统计信息等等既能帮助用户从多个维度分析线程池的使用情况又能在出现问题第一时间通知到用户从而避免故障或加速故障恢复。 1. 负载监控和告警 线程池负载关注的核心问题是基于当前线程池参数分配的资源够不够。对于这个问题我们可以从事前和事中两个角度来看。事前线程池定义了“活跃度”这个概念来让用户在发生Reject异常之前能够感知线程池负载问题线程池活跃度计算公式为线程池活跃度 activeCount/maximumPoolSize。这个公式代表当活跃线程数趋向于maximumPoolSize的时候代表线程负载趋高。事中也可以从两方面来看线程池的过载判定条件一个是发生了Reject异常一个是队列中有等待任务支持定制阈值。以上两种情况发生了都会触发告警告警信息会通过大象推送给服务所关联的负责人。 2. 任务级精细化监控 在传统的线程池应用场景中线程池中的任务执行情况对于用户来说是透明的。比如在一个具体的业务场景中业务开发申请了一个线程池同时用于执行两种任务一个是发消息任务、一个是发短信任务这两类任务实际执行的频率和时长对于用户来说没有一个直观的感受很可能这两类任务不适合共享一个线程池但是由于用户无法感知因此也无从优化。动态化线程池内部实现了任务级别的埋点且允许为不同的业务任务指定具有业务含义的名称线程池内部基于这个名称做Transaction打点基于这个功能用户可以看到线程池内部任务级别的执行情况且区分业务任务监控示意图如下图所示 3. 运行时状态实时查看 用户基于JDK原生线程池ThreadPoolExecutor提供的几个public的getter方法可以读取到当前线程池的运行状态以及参数如下图所示 动态化线程池基于这几个接口封装了运行时状态实时查看的功能用户基于这个功能可以了解线程池的实时状态比如当前有多少个工作线程执行了多少个任务队列中等待的任务数等等。效果如下图所示 3.4 实践总结 面对业务中使用线程池遇到的实际问题我们曾回到支持并发性问题本身来思考有没有取代线程池的方案也曾尝试着去追求线程池参数设置的合理性但面对业界方案具体落地的复杂性、可维护性以及真实运行环境的不确定性我们在前两个方向上可谓“举步维艰”。最终我们回到线程池参数动态化方向上探索得出一个且可以解决业务问题的方案虽然本质上还是没有逃离使用线程池的范畴但是在成本和收益之间算是取得了一个很好的平衡。成本在于实现动态化以及监控成本不高收益在于在不颠覆原有线程池使用方式的基础之上从降低线程池参数修改的成本以及多维度监控这两个方面降低了故障发生的概率。希望本文提供的动态化线程池思路能对大家有帮助。 四、参考资料 [1] JDK 1.8源码[2] 维基百科-线程池[3] 更好的使用Java线程池[4] 维基百科Pooling(Resource Management)[5] 深入理解Java线程池ThreadPoolExecutor[6]《Java并发编程实践》作者简介 致远2018年加入美团点评美团到店综合研发中心后台开发工程师。陆晨2015年加入美团点评美团到店综合研发中心后台技术专家。招聘信息 美团到店综合研发中心长期招聘前端、后端、数据仓库、机器学习/数据挖掘算法工程师欢迎感兴趣的同学发送简历到techmeituan.com邮件标题注明美团到店综合研发中心-上海
http://www.zqtcl.cn/news/766407/

相关文章:

  • 重庆定制网站建设公司郑州网站模板
  • 网站 建设 领导小组wordpress下拉 友情链接
  • 做网站用php广州最新新闻
  • 福州市住房和城乡建设局网站18款禁用观看黄入口
  • 西安网站制作工作室网页怎么做成网站
  • 做h5网站公司百度知道网页入口
  • 网站建设 中企动力上海在线设计房屋效果图
  • 河南宝盈建设集团有限公司网站代理二级分销系统
  • 青岛高级网站建设价格对外宣传及网站建设文件稿
  • 网络营销中自建网站建设局是干嘛的单位
  • 做网站的公司 贵阳流媒体网站建设
  • 北京建网站重庆安全建设工程信息网
  • 做公司网站的尺寸一般是多大无障碍浏览网站怎么做
  • 网站登陆界面psd手机一元云购网站建设
  • 网站规范化建设wordpress iis7.5 伪静态
  • 济南网站设计建设公司深圳seo外包公司
  • 重庆信息网站推广网站做推广如何设计二维码
  • 学历低的人不适合学编程小红书seo关键词优化多少钱
  • pc网站制作公司企业邮箱格式模板
  • 河南5G网站基站建设信息wordpress自定义文章页面模板下载
  • 宁波三优互动网站建设公司怎么样手机app商城
  • 散热器 东莞网站建设php模板源码
  • 怎么申请域名建网站凡科网站建设总结
  • 温州网站设计定制外贸人才网哪家最好
  • 永康门业微网站建设做一个网站要多长时间
  • 南山网站建设哪家好四川省微信网站建设公
  • 网件路由器做网站网站建设中 提示
  • 全运网站的建设徐州网络推广公司排名
  • 成品网站源码1688体验区南宁网络推广服务商
  • 广州品牌网站开发公司网站建设价位