在操做系统中,线程是一个很是重要的资源,频繁建立和销毁大量线程会大大下降系统性能。Java线程池原理相似于数据库链接池,目的就是帮助咱们实现线程复用,减小频繁建立和销毁线程
java
ThreadPoolExecutor是线程池的核心类。首先看一下如何建立一个ThreadPoolExecutor。下面是ThreadPoolExecutor经常使用的一个构造方法:数据库
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
使用案例并发
/** * 阻塞的线程池 */ private ThreadPoolExecutor executor = new ThreadPoolExecutor( 0, // corePoolSize:线程池维护线程的最少数量 4, // maximumPoolSize:线程池维护线程的最大数量 10000, // keepAliveTime:线程池维护线程所容许的空闲时间 TimeUnit.MILLISECONDS, // unite:线程池维护线程所容许的空闲时间的单位 new LinkedBlockingQueue<>(200), // workQueue:线程池所使用的缓冲队列 new CallerBlockedPolicy() // handler:线程池对拒绝任务的处理策略,自定义拓展 );
execute()
方法提交时,会执行如下判断:
corePoolSize
,则建立新线程来处理任务,即便线程池中的其余线程是空闲的;corePoolSize
且小于 maximumPoolSize
,则只有当workQueue
满时才建立新的线程去处理任务;corePoolSize
和 maximumPoolSize
相同,则建立的线程池的大小是固定的,这时若是有新任务提交,若workQueue
未满,则将请求放入workQueue
中,等待有空闲的线程去从workQueue
中取任务并处理;corePoolSize
的时候,把该任务封装成一个Worker
对象放入等待队列;SynchronousQueue
,但如今尚未研究过该队列,这里暂时还无法介绍;LinkedBlockingQueue
。若是使用这种方式,那么线程池中可以建立的最大线程数就是corePoolSize
,而maximumPoolSize
就不会起做用了(后面也会说到)。当线程池中全部的核心线程都是RUNNING状态时,这时一个新的任务提交就会放入等待队列中。ArrayBlockingQueue
。使用该方式能够将线程池的最大线程数量限制为maximumPoolSize
,这样可以下降资源的消耗,但同时这种方式也使得线程池对线程的调度变得更困难,由于线程池和队列的容量都是有限的值,因此要想使线程池处理任务的吞吐率达到一个相对合理的范围,又想使线程调度相对简单,而且还要尽量的下降线程池对资源的消耗,就须要合理的设置这两个数量。
setMaximumPoolSize()
方法来从新设定线程池的容量。corePoolSize
的时候,若是这时没有新的任务提交,核心线程外的线程不会当即销毁,而是会等待,直到等待的时间超过了keepAliveTime
;Executors.defaultThreadFactory()
来建立线程。使用默认的- - - - ThreadFactory来建立线程时,会使新建立的线程具备相同的NORM_PRIORITY优先级而且是非守护线程,同时也设置了线程的名称。RejectedExecutionHandler
类型的变量,表示线程池的饱和策略。若是阻塞队列满了而且没有空闲的线程,这时若是继续提交任务,就须要采起一种策略处理该任务。线程池提供了4种策略:
经过线程池提供的参数进行监控。线程池里有一些属性在监控线程池的时候可使用性能
总结一下线程池添加任务的整个流程:this