Java经过Executors提供四种线程池,分别为:
newCachedThreadPool建立一个可缓存线程池,若是线程池长度超过处理须要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 建立一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 建立一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 建立一个单线程化的线程池,它只会用惟一的工做线程来执行任务,保证全部任务按照指定顺序(FIFO, LIFO, 优先级)执行。算法
熟悉这四种线程池,首先 先了解ThreadPoolExecutor缓存
ThreadPoolExecutor中定义了如下几个属性比较重要并发
corePoolSize:线程池中的线程数量,线程池中默认开启几个线程处理 任务队列中的任务函数
(注:这个并非固定的,根据队列(workQueue)的不一样实现类型而改变)spa
maximumPoolSize:线程池中的最大线程数量,这个属性感受和上面的corePoolSize冲突,明明上面定义了线程数据了,怎么这里又控制了线程
最大线程数量,其实 同样和 上面提到的同样(根据队列(workQueue)的不一样实现类型 ,须要用到该属性进行相应的 任务拒绝策略)code
keepAliveTime;//超过corePoolSize的空闲线程,在多长时间内会被销毁
TimeUnit unit;//keepAliveTime的单位
BlockingQueue<Runnable> workQueue:任务队列,被提交的但还没有被执行的任务blog
主要有如下几种实现类型接口
SynchronousQueue:直接提交的队列,该队列没有容量,每个擦入操做都要对应一个相应的删除操做,反之每一个删除操做对应相应的插入操做。队列
SynchronousQueue不保存任务,它老是将任务提交给线程执行,若是没有空闲的进程,则尝试建立新的进程,若是进程
已达到maximumPoolSize设置的最大线程数,则执行拒绝策略
ArrayBlockingQueue:有界任务队列,ArrayBlockingQueue的构造函数必须带一个容量参数(例如n),表示该队列的最大容量。
当有新任务执行时,这个定义当前线程数为t,构造函数的容量参数为n,当前队列长度为l
1.t<corePoolSize时,建立新的线程之心
2.t>corePoolSize且l<n时,插入到任务队列,等待空闲线程执行
3.t>corePoolSize且l>=n时,建立新的线程执行新任务
4.t>maximumPoolSize时,执行拒绝策略。
LinkedBlockingQueue:无界任务队列,当有新任务执行时,若是线程池中线程数小于corePoolSize则建立新的线程,不然进入队列等待。
若是没有任务建立速度和处理速度差别很大,无界队列会保持快速增加,直到耗尽系统内存
PriorityBlockingQueue:优先级队列,能够控制任务的执行前后顺序,是一个特殊的无界队列。不管有界的队列无界的队列,都是按照先进先出算法
处理任务(絮叨),而该队列破例能够根据任务自身的优先级顺序前后执行。
ThreadFactory threadFactory//线程工厂,用于建立线程,通常默认
RejectedExecutionHandler handler;//拒绝策略,当任务太多来不及处理,如何拒绝任务
JDK内置的拒绝策略以下:
AbortPolity策略:该策略会直接抛出异常,阻止系统正常工做
CallerRunsPolity策略:只要线程为关闭,该策略直接在调用者线程中,运行当前被丢弃的任务
DiscardOledstPolicy策略:该策略将丢弃最老的一个请求,也就是即将被执行的一个任务,并尝试再次提交当前任务。
DiscardPlicy 策略:该策略默默的丢弃没法处理的任务,不予任务处理。
若是以上策略不能知足实际应用需求,能够扩展RejectedExecutionHandler 接口
public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }
其中,r为请求执行的任务,executor为当前线程池。
了解了ThreadPoolExecutor的上述属性,而后分析Executors提供四种线程池就很简单了
Executors.newFixedThreadPool(nThreads)
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
返回了一个corePoolSize, maximumPoolSize大小相等而且使用了LinkedBlockingQueue任务队列的线程池,由于对于固定大小的线程池而言,不存在线程数量的动态
变化,所以corePoolSize,和maximumPoolSize能够相等,同时它使用无界队列存放没法当即执行的任务,当任务提交很是频繁的时候,该队列可能迅速膨胀,从而耗尽
系统资源。
Executors.newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
返回单线程的线程池,是newFixedThreadPool()方法的一种退化,只是简单的将线程池的线程数量设置为1
Executors.newCachedThreadPool()
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
返回corePoolSize为0 maximumPoolSize无穷大的线程池,这意味着在没有任务时,该线程内无线程,而当任务被提交时,该线程池会使用空闲的线程执行任务,若无空闲
线程,则将任务加入SynchronousQueue队列,而SynchronousQueue队列是一种直接提交的队列,它总会迫使线程池增长新的线程执行任务,当任务执行完毕后,
因为corePoolSize为0,所以空线程又会在指定时间内(60s)被回收。
对于newCachedThreadPool(),若是同时又大量任务被提交,而任务的执行又不那么快时,那么系统便会开启等量的线程处理,这样的作法可能会很快耗尽系统的资源。