【JUC线程池】ExecutorService以及Executors线程池类型

        JUC:java.util.concurrent是Java的并发包。我认为当我们了解关于Java的多线程,就应该知道线程池从何而来:是为了解决在多线程并发的环境下,对于减少线程的创建和释放内存和资源下所以才会有线程池的概念。所以第一步就要先了解如何创建线程池。

线程池创建

        初次了解线程池肯定会了解到ThreadPoolExecutor类,其内部有四种有参构造方法均是为了创建线程池。接下来主要示范的是七个形参的构造方法。

/**
 * int corePoolSize:核心线程数,必定大于0
 * int maximumPoolSize:最大线程数,必定大于等于0并且大于等于核心线程数
 * long keepAliveTime:空闲线程最大存活时间,必定大于0,时间到期就被释放
 * TimeUnit unit:时间单位(用TimeUtil指定)
 * BlockingQueue<Runnable> workQueue:任务队列,不为null
 * ThreadFactory threadFactory:创建线程工厂,不为null,有默认值
 * RejectedExecutionHandler handler:任务的拒绝策略,不为null,有默认值
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
}

corePoolSize:如果创建的线程数未达到指定的核心线程数,则会继续创建新的核心线程数达到指定值,而后创建的线程均不为核心线程,而是非核心线程。

maximnmPoolSize:如果最大线程数等于核心线程数,则无法创建非核心线程。如果非核心线程处于空闲时,超过设置的空闲时间就会被回收,释放占用的资源。

keepAliveTime非核心线程的存活时间。

BlockingQueue<Runnable>:任务队列,指存放被提交但尚未被执行的任务的队列。

ThreadFactory(可无):线程工厂,用于创建线程,默认是Executors.defaultThreadFactory()。

RejectedExecutionHandler(可无):当线程边界和队列容量已经达到最大时用于处理阻塞的程序。默认是AbortPolicy:任务满了将其多余的任务丢掉且抛异常。

任务队列

直接提交型(SynchronousQueue)

(1)SynchronousQueue没有容量。

(2)提交的任务不会被真实的保存在队列中,而总是将新任务提交给线程执行。如果没有空闲的线程,则尝试创建新的线程。如果线程数大于最大值maximumPoolSize,则执行拒绝策略。

有界型(ArrayBlockingQueue)

(1)创建队列时,指定队列的最大容量。

(2)若有新的任务要执行,如果线程池中的线程数小于corePoolSize,则会优先创建新的线程。若大于corePoolSize,则会将新任务加入到等待队列中。

(3)若等待队列已满,无法加入。如果总线程数不大于线程数最大值maximumPoolSize,则创建新的线程执行任务。若大于maximumPoolSize,则执行拒绝策略。

无界型(LinkedBlockingQueue)

(1)与有界队列相比,除非系统资源耗尽,否则不存在任务入队失败的情况。

(2)若有新的任务要执行,如果线程池中的线程数小于corePoolSize,线程池会创建新的线程。若大于corePoolSize,此时又没有空闲的线程资源,则任务直接进入等待队列。

(3)当线程池中的线程数达到corePoolSize后,线程池不会创建新的线程。

(4)若任务创建和处理的速度差异很大,无界队列将保持快速增长,直到耗尽系统内存。

(5)使用无界队列将导致在所有 corePoolSize 线程都忙时,新任务在队列中等待。这样,创建的线程就不会超过 corePoolSize(因此,maximumPoolSize 的值也就无效了)。当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。

优先任务型(PriorityBlockingQueue)

(1)带有执行优先级的队列。是一个特殊的无界队列。

(2)ArrayBlockingQueue和LinkedBlockingQueue都是按照先进先出算法来处理任务。而PriorityBlockingQueue可根据任务自身的优先级顺序先后执行(总是确保高优先级的任务先执行)。
————————————————
版权声明:本文为CSDN博主「J_bean」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/j_bean/article/details/78612988

任务拒绝策略

AbortPolicy

DiscardPolicy

DiscardOldestPolicy

CallerRunsPolicy

ExecutorService

        ExecutorService是Executor的子接口。是对线程池的实现。Executor接口中只有一个execute()方法,里面传递的是Runnable接口,就是相当于传入一个线程。而ExecutorService中就有几种方法是对线程的运用。注意:Executor与下文讲的Executors是不一样的。

shutdown():在完成已经提交的任务后销毁线程

shutdownNow():直接停止现在的任务并返回之前执行的任务后销毁线程

isShutdown():判断线程是否已经被销毁

isTerminated():判断所有任务是否执行完毕

submit(Runnable task):提交Callable或者Runnable任务

那么讲完了ExecutorService中对线程的方法操作,该如何去创建对应的线程池呢? 

线程池类型

缓存型

通过Executors.newCachedThreadPool();创建。通过其源码可以发现:没有核心线程数,有很多的非核心线程数,存活时间是大约2分钟。由此可见适用于生命周期短的任务。

单线程型

通过Executors.newSingleThreadExecutor();创建。通过其源码可以发现:只有1个核心线程数并且最大线程数也为1,没有存活时间,用的是无界型任务队列,保证任务FIFO顺序执行

固定线程型

通过Executors.newFixedThreadPool();创建。通过其源码可以发现:核心线程数等于最大线程数,非核心线程不存活,也就是相当于只执行传来参数的线程数量。

固定核心线程型

通过Executors.newScheduledThreadPool();创建。通过其源码可以发现:传入的参数就是核心线程数,非核心线程数很多且不存活。

猜你喜欢

转载自blog.csdn.net/m0_65563175/article/details/129819813