这篇文章主要介绍“Java线程池是怎么实现的”,在日常操作中,相信很多人在Java线程池是怎么实现的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java线程池是怎么实现的”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
创新互联公司服务项目包括大荔网站建设、大荔网站制作、大荔网页制作以及大荔网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,大荔网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到大荔省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!Java 线程池怎么玩
想玩明白 Java 的线程池,只需要的知道构建线程池的几个参数具体的含义基本上就明了了。那么接下来,就让我们一一瓦解这些参数。
corePoolSize
我们假设有 N 个任务需要提交到线程池去处理,当任务数量 N 小于核心线程数 corePoolSize(后文用 C 来代替) 的时候,线程池会不断新建线程来处理用户提交进来的任务即使有线程空闲。C 其实代表的是线程池通常情况下会保留的线程数量(如果将线程池比作一个工厂,C 可以类比为工厂的正式编制人员数量),当任务数量 N 超过核心线程数量 C 的时候,线程池就要用到下一个参数 workQueue 了。
workQueue
当用户提交的任务数量变多了,这时候线程池中的线程数量已经达到核心线程数 C,那么只能将提交过来的任务暂存在 workQueue 队列中。每当有线程处理完手头上活的时候就会来工作队列领取任务,如果队列中没有任务,那么当前线程就阻塞在队列上,等待任务。工作队列可以简单分为 2 种:无界队列和有界队列。
无界队列
如果我创建线程池的传入的是无界队列,那么意味着用户可以源源不断的提交任务到线程池,而不需要担心线程池拒绝接收,例如 LinkedBlockingQueue 就是一种选择。
有界队列
如果我们传入的是有界队列,例如 ArrayBlockingQueue,那就需要考虑队列存满了怎么办?不用担心这个时候线程池会帮忙找一些临时工来干活,这就需要用到下一个参数 maximumPoolSize 了。
maximumPoolSize
此时所有的核心线程都在干活,而且工作队列也存满了任务。如果还是有任务提交进来,那么线程池会再创建新的线程来帮助工作(可以类比为一个工厂,管理员发现任务太多,仓库也堆满了任务需要雇佣一些临时工来帮助干活)。当然临时工也不能雇佣太多,毕竟工厂资源有限,需要设定工厂里面工人较大上限,这个就是 maximumPoolSize 了。然而疯狂的用户哪管你能不能处理完任务,还是不断的提交任务进来,这个时候线程池忍无可忍了,关门拒绝用户提交新的任务,这时候 RejectedExexcutionHandler 就要开始发挥作用了。
RejectedExexcutionHandler
线程池共提供了如下 4 种拒绝策略AbortPolicy 策略会抛出一个 RejectedExecutionException 异常给用户,告诉它任务被拒绝了。DiscardPolicy 策略当任务来临时候不会给用户任何反馈,悄无声息拒绝任务。DiscardOldestPolicy 策略比较霸道,它会直接将最早存储在工作队列的任务丢弃掉,然后再试图去执行当前提交进来的任务。CallerRunsPolicy 策略呢虽然线程池中的工人不帮忙处理任务了,它会占用用户线程去处理当前任务,这也就意味着用户线程要处理完当前任务才可以做其他事情。
使用上面的几个核心参数完美的解决了任务的提交流程和工作分配问题,接下来就要来考虑一下后面的工作了。用户提交了一大波任务以后,就不在提交了。这时候线程池的中工人都还在呢,如果一直保留这些资源但是又没有活干,会造成资源的浪费。这时候就需要用到 keepAliveTime 和 TimeUnit 参数了。
keepAliveTime 和 TimeUnit
这 2 个参数组合起来决定了一个工人最多可以在工厂里愉快的摸鱼时间,如果摸鱼时间超过这个限度,这个工人资源就会被释放,也就是这个空闲线程资源就被回收掉咯。当然啦,线程池会保留核心线程在工厂里面等待新任务,以备有新任务的到来,我们也可以通过 public void allowCoreThreadTimeOut(boolean value) 方法设置参数,来允许线程池也可以释放核心线程。
threadFactory
还剩下最后一个参数,它比较简单,主要用来创建线程,例如我们想让线程池中的线程做一些定制化的工作就可以自己来定义线程工厂,这样线程池创建线程的时候就使用我们指定的工厂了。
你可能会觉得构建一个线程还要设置这么参数,太麻烦了,贴心的 JDK 帮我们在 Executors 中准备了几个静态工厂方法,我们一起看一下它们的特性:newFixedThreadPool(int nThreads) 可以创建一个固定线程数量的线程池,同时它的工作队列是一个无界队列。newSingleThreadExecutor() 可以创建只有一个线程工作的线程池,同时它的工作队列也是无界队列。newCachedThreadPool() 可以创建一个没上限工作线程的线程池,它使用了 SynchronousQueue 只要有任务过来,如果有空闲的线程,会优先利用空闲的线程池,没有空闲线程就会新创建线程。newSingleThreadScheduledExecutor() 创建的是一个具有延迟和循环执行任务线程池,同时它内部也只有一个线程,它的工作队列是一个具有延迟功能的队列 DelayedWorkQueue。newWorkStealingPool() 这种方法是 Java 8 提供的,它实际创建的是一个 ForkJoinTool 而不是 ThreadPoolExecutor 的实例。如上即为 5 中创建线程池的工厂方法,大家根据需要选择适合自己工作的,当然也可以直接使用 ThreadPoolExecutor 来创建一个。
到此,关于“Java线程池是怎么实现的”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!