文档章节

并发编程 — 详解线程池

larryee
 larryee
发布于 2015/01/14 21:35
字数 1089
阅读 11
收藏 1
 本文将讲述如何通过JDK提供的API自定义定制的线程池 

Java代码   收藏代码
  1. //固定线程数 -- FixedThreadPool  
  2. public static ExecutorService newFixedThreadPool(int nThreads) {  
  3.     return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,  
  4.             new LinkedBlockingQueue<Runnable>());  
  5. }  
  6.   
  7. //单条线程  --  SingleThreadExecutor  
  8. public static ExecutorService newSingleThreadExecutor() {  
  9.     return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(11, 0L,  
  10.             TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));  
  11. }  
  12.   
  13. //线程数自增长    --  CachedThreadPool  
  14. public static ExecutorService newCachedThreadPool() {  
  15.     return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,  
  16.             new SynchronousQueue<Runnable>());  
  17. }  


      从上面代码可以看出,通过Executors创建的三种线程池其实内部都是调用 
ThreadPoolExecutor进行创建
 

Java代码   收藏代码
  1. public ThreadPoolExecutor(int corePoolSize,  
  2.                               int maximumPoolSize,  
  3.                               long keepAliveTime,  
  4.                               TimeUnit unit,  
  5.                               BlockingQueue<Runnable> workQueue) {  
  6.         this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,  
  7.              Executors.defaultThreadFactory(), defaultHandler);  
  8.     }  


corePoolSize 指定线程池中线程的数量
maximumPoolSize 指定线程池中最大线程数量
keepAliveTime 空闲线程存活时间,指超过corePoolSize的线程
unit keepAliveTime的时间单位
workQueue 任务队列,被提交但未被执行的任务存放容器
threadFactory 线程创建工厂,请参考上一章
handler 拒绝策略,当任务太多来不及处理时的拒绝策略



      需要重点注意的是workQueue和handler两个参数 


workQueue: 
      参数workQueue是指被提交但未被执行的任务所存放的队列容器,它是一个BlockingQueue接口,仅用于存放Runaable对象.根据队列功能的分类,在ThreadPoolExecutor中可以使用两种队列 

直接提交队列: 
      SynchronousQueue,SynchronousQueue是没有容量的容器,每一个插入的操作都需要等待相应的删除操作,SynchronousQueue不保存任务,它总是马上将任务提交给线程执行,如果没有空闲的线程则会尝试创建新的线程,如果线程数量已经达到最大值,则执行拒绝策略,使用SynchronousQueue通常需要设置很大的maximumPoolSize 


有界的任务队列: 
      有界队列可以使用ArrayBlockingQueue,ArrayBlockingQueue的构造函数必须传入一个容量参数,表示队列的最大容量,当使用有界队列并有新任务时,若然线程池线程数量小于corePoolSize则会创建现场,若然大于corePoolSize则会将新任务加入任务队列,当任务队列已满无法加入时,则在总线程数不大于maximumPoolSize的前提下创建线程,若大于maximumPoolSize则执行拒绝策略,使用有界队列除非系统非常繁忙,否则确保核心线程数在corePoolSize 


无界的任务队列: 
      无界任务队列可以使用LinkedBlockingQueue,与有界队列相比,除非系统资源耗尽,否则不会存在任务入队失败的情况.若任务创建和处理速度差异很大,无界队列会快速膨胀导致系统资源耗尽 


优先任务队列: 
      优先任务队列使用PriorityBlockingQueue实现,PriorityBlockingQueue是一个特殊的无界队列,创建PriorityBlockingQueue时可以传入Comparator对任务进行优先级处理,PriorityBlockingQueue和无界队列可能会发生的问题一样,不过PriorityBlockingQueue能控制任务的优先级别 


handler 
      handler参数指定了拒绝策略,即当任务数量超过线程池实际负载的时候,该如何处理被提交的任务,JDK内置提供了4种拒绝策略 

AbortPolicy策略: 
      该策略会直接抛出异常 

CallerRunsPolicy策略: 
      只要线程池未关闭,该策略直接在调用者线程中运行当前被放弃任务 

DiscardOledestPolicy策略: 
      该策略丢弃最老的一个请求,即即将被执行的任务,并尝试再提交当前任务 

DiscardPolicy策略: 
      该策略丢弃无法处理的任务,不做任何处理 


     所有拒绝策略都继承自RejectedExecutionHandler接口,读者可根据实际情况需要扩展该接口实现自己的拒绝策略 



扩展线程池 
      ThreadPoolExecutor也是一个可扩展的线程池,它提供了beforeExecute,afterExecute,terminated3个接口对线程池调用任务进行控制 

Java代码   收藏代码
  1. public class TestThreadPoolExecutor extends ThreadPoolExecutor {  
  2.   
  3.     @Override  
  4.     protected void beforeExecute(Thread t, Runnable r) {  
  5.         super.beforeExecute(t, r);  
  6.     }  
  7.   
  8.     @Override  
  9.     protected void afterExecute(Runnable r, Throwable t) {  
  10.         super.afterExecute(r, t);  
  11.     }  
  12.   
  13.     @Override  
  14.     protected void terminated() {  
  15.         super.terminated();  
  16.     }  
  17. }  


总结: 
      Executor框架提供了多功能的定制方式让开发者快速方便的实现定制的线程池,从而减少不必要的开发工作,且本身也提供多个扩展点让开发者自行扩展实现独特的业务逻辑

本文转载自:http://blog.csdn.net/u012992171/article/details/28410201

上一篇: FrameLayout
larryee
粉丝 0
博文 51
码字总数 393
作品 0
浦东
私信 提问
后台开发常问面试题集锦(问题搬运工,附链接)

Java基础问题 String的’+’的性能及原理 java之yield(),sleep(),wait()区别详解-备忘笔记 深入理解Java Stream流水线 抽象 & abstract关键字 Java final 修饰符知识点总结(必看篇) Java中的...

大黄有故事
2017/11/18
0
0
Java系列文章(全)

JVM JVM系列:类装载器的体系结构 JVM系列:Class文件检验器 JVM系列:安全管理器 JVM系列:策略文件 Java垃圾回收机制 深入剖析Classloader(一)--类的主动使用与被动使用 深入剖析Classloader(二...

www19
2017/07/04
0
0
互联网技术栈 『Contents Catalog』

image.png 编程语言 Java书单——由入门到上天 UML-类间关系 Java解读-ThreadLocal详解与应用 并发编程-Concurrent用户指南 Java并发编程-原子性变量 Java 并发工具包-常用线程池 基于事件驱...

高广超
2017/11/03
0
0
.NET线程池最大线程数的限制-记一次IIS并发瓶颈

.NET ThreadPool 最大线程数的限制 IIS并发瓶颈,有几个地方,IIS线程池的最大队列数,工作进程数,最大并发数。这些这里就不展开。主要是最近因为过度使用Task 导致的线程数占用过多,所以实...

鬼柒
2018/11/15
0
0
Java 并发编程源码解析汇总篇

java并发编程,内存模型 java并发编程,volatile内存实现和原理 Java并发编程,并发基础 Java 并发编程,线程池(ThreadPoolExecutor)源码解析 Java并发编程,Executor 框架介绍 Java并发编...

郑加威
2018/12/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
144
8
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
2
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部