线程池中的corenum和maxnum不同之处有哪些?
2018-01-09
线程池中的corenum和maxnum不同之处有哪些?下面由java培训机构做详细介绍:
(1) 直接提交的队列:该功能由SynchronizedQueue对象提供。SynchronizedQueue是一个特殊的阻塞队列。SynchronizedQueue没有容量,每一个插入操作都要等待一个相应的删除操作,反之每一个删除操作都需要等待对应的插入操作。使用SynchronizedQueue时提交的任务不会被真实的保存,而总是将新任务提交给线程执行,如果没有空闲的线程则尝试创建新的线程,如果线程数量达到最大值就执行决绝策略。使用SynchronizedQueue队列通常要设置很大的maxnumPoolSize,否则很容易执行拒绝策略。可以当做大小为0的队列来理解。
(2) 有界的任务队列:有界的任务队列可以使用ArrayBlockingQueue实现。当使用有界的任务队列时,若有新的任务需要执行,如果线程池的实际线程数小于核心线程数,则有优先创建新的线程,若大于核心线程数,则会将新任务加入等待队列。若队列已满,无法加入则在总线程数不大于最大线程数的前提下,创建新的线程。若大于最大线程数,则执行拒绝策略。也就是说,有界队列仅当任务队列满时才可能将线程数提升到核心线程数只上,否则确保线程数维持在核心线程数大小。
(3) 无界任务队列:无界任务队列可以通过LinkedBlockingQueue类来实现。与有界队列相比,除非系统资源耗尽,否则无界队列不存在任务入队失败的情况。当有新的任务到来,系统的线程数小于核心线程数时线程池会生成新的线程执行任务,但当系统线程数大于核心线程数后,就不会继续增加。若后续有新的任务,则将任务放入无界队列中等待。
(4) 优先任务队列:优先任务队列是带有执行优先级的队列,通过PriorityBlockingQueue实现,可以控制任务的执行先后顺序,是一个特殊的无界队列。无论是有界队列还ArrayBlockingQueue还是未指定大小的无界队列LinkedBlockingQueue,都是按照先进先出算法处理任务的,而有限队列则可以根据任务自身的优先级顺序执行,在确保系统性能的同时,也能有很好的质量保证。
回过头看Executor框架提供了几种线程池,newFixedThreadPool()返回的固定大小线程池中核心线程数和最大线程数一样,并且使用了无界队列。因为对于固定大小的线程池来说,不存在线程数量的动态变化,所以最大线程数等于核心线程数。同时,使用无界队列存放无法立即执行的任务,当任务提交非常频繁时,队列可能迅速膨胀,从而耗尽系统资源。
newSingleThreadExecutor()返回的单线程线程池,是固定大小线程池的一种退化,只是简单的将线程池数量设置为1。
newCachedThreadExecutor()返回核心线程数为0,最大线程数为无穷大的线程池。使用直接提交队列SynchronizedQueue。
当Executor提供的线程池不满足使用场景时,则需要使用自定义线程池,选择合适的任务队列来作为缓冲。不同的并发队列对系统和性能的影响均不同。