下载:TuringJAVAInternetArchitectPhase5JavaThreadPoolExecutor详解Ex??ecutors我们最常用来完成线程池的创建线程的使用主要在上面的类中提供图类。在上面的类图中,包含了一个Executor框架,它是一个基于一组执行策略调用来调度、执行和控制异步任务的框架。目的是提供一种机制,将任务提交与任务工作方式分开。它包含三个执行器接口:Executor:运行新任务的简单接口ExecutorService:扩展了Executor,增加了管理执行器生命周期和任务生命周期的方法。ScheduleExcutorService:扩展ExecutorService,支持Future和周期性执行任务的线程池的好处减少资源消耗——重用现有线程,降低对象创建和销毁的成本,提高性能和提高响应速度——可以有效控制最大并发数threads,提高系统资源的利用率,同时防止资源过度竞争,防止阻塞。当任务到达时,可以立即执行任务,无需等待创建线程,提高线程的可管理性——提供定时执行、周期执行、单线程、并发控制等功能。newThread的缺点每次newThread都会创建一个新的对象,性能差的线程缺乏统一管理,可能会无限创建新线程,相互竞争,可能会占用太多系统资源导致崩溃或OOM(outofmemory内存溢出)),这种问题的原因并不是简单的newThread,而是可能是因为程序bug或者设计缺陷导致不断newThreads。缺少更多的功能,比如更多的执行,周期性的执行,线程中断。线程池核心类-ThreadPoolExecutor参数说明:ThreadPoolExecutor一共有七个参数,这七个参数组合起来就构成了线程池的强大功能。corePoolSize:中心线程数maximumPoolSize:最大线程数workQueue:阻塞队列,存放等待执行的任务,非常重要,会严重影响线程池的运行。当我们向线程池提交一个新的任务时,线程池会根据当前池中运行的线程数来决定任务的处理方式。有3种处理方式:1.直接切换(SynchronusQueue)2.无界队列(LinkedBlockingQueue)最大可以创建的线程数是corePoolSize,那么maximumPoolSize就不行了。当线程池中的所有核心线程都在运行时,新的任务提交会被放入等待队列。3、有界队列(ArrayBlockingQueue)的最大maximumPoolSize可以减少资源消耗,但是这种方式使得线程池调度线程更加困难。因为线程池和队列的容量是有限的。因此,如果我们想让线程池的吞吐率和处理任务都达到一个合理的范围,又想让我们的线程调度相对简单,尽可能减少资源消耗,就需要对这两种数量分配技巧进行合理的限制:[如果想降低资源消耗,包括降低cpu利用率、操作系统资源消耗、上下文切换开销等,可以设置更大的队列容量和更小的线程池容量,这样会降低线程池的吞吐量.如果我们提交的任务经常阻塞,我们可以调整maximumPoolSize。如果我们的队列容量小,我们需要将线程池大小设置的大一些,这样cpu的使用率会相对高一些。但是如果线程池的容量设置太大,当高级任务数量过多时,并发量会增加,所以线程间的调度是一个需要考虑的问题。这可能反过来会降低处理任务的吞吐量。]keepAliveTime:没有任务执行时线程持续多久终止(当线程中的线程数大于corePoolSize时,如果此时没有新任务提交,则核心线程之外的线程不会立即销毁,但要等到超过keepAliveTime)unit:keepAliveTime的时间单位threadFactory:线程工厂,用于创建线程,有一个默认工厂创建线程,让新创建的线程具有相同的优先级,是否rejectHandler:当拒绝处理任务时的策略(阻塞队列已满)队列中的任务并执行当前任务,DiscardPolicy直接丢弃当前任务)corePoolSize、maximumPoolSize、workQueue的关系:如果运行线程数小于corePoolSize,则直接创建新线程处理任务。即使线程池中的其他线程空闲。如果运行的线程数大于corePoolSize小于maximumPoolSize,那么只有当workQueue满了才会创建新的线程来处理任务。如果corePoolSize与maximumPoolSize相同,那么创建的线程池大小是固定的。这时候提交一个新任务,当workQueue未满时,将request放入workQueue中。等待空线程从workQueue中取出任务。如果此时workQueue也已满,则使用另一个拒绝策略参数执行拒绝策略。
