java多线程-线程池

2019-02-28  本文已影响0人  探索者_逗你玩儿

java中不可避免的就是使用线程池TheadPoolExecutors,其中线程池的创建有两种方式:一种偷懒的做法就是通过Executors帮助类来简化线程池的创建

Executors.newFixedThreadPool
Executors.newFixedThreadPool
Executors.newSingleThreadExecutor
Executors.newCachedThreadPool
Executors.newScheduledThreadPool
Executors.newSingleThreadScheduledExecutor

另外一种是通过TheadPoolExecutor 来创建。虽说明面上创建方式是两种,但是底层实现就是一套,第一套创建方式是在第二套的基础上进一步封装而来的,既然明白了其中的关系,那么我们就直接跳过第一种方式,直接来看第二种实现方式,弄懂了第二种方式,第一种方式就水到渠成了。

首先我们来看看TheadPoolExecutor的类图,看懂这张图对于我们后面理解线程池有很大的帮助 diagram.png
通过类图可以看到线程池有两种提交任务的方式,一个是在Executor中定义的execute方法,另外一个是ExecutorService提供的submit,这两种方式的区别是execute直接执行提交的任务,而submit方法是提交任务后返回一个Future,通过Futur.get()我们可以获取到任务执行的结果,但是这种方式会阻塞当前的线程执行直到拿到返回结果,针对这种情况jdk8增加来CompletableFuture 异步执行的Future,这个东西我们后面再来针对的分析。

接下来我们看看如何创建TheadPoolExecutor,通过构造函数我们逐一说明一下各个参数的作用。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

corePoolSize 核心线程数

maximumPoolSize 最大线程数

keepAliveTime 线程空闲时间

TimeUnit 时间单位

workQueue 任务队列,用来指定线程池用什么队列来装载提交的任务。

感觉可以理解为这个入队列会总是失败,就相当于没有这个队列一样。这样就能在maxPoolSize条件下尽可能快的创建(或选择空闲的线程)来执行新提交的任务。
如果提交的任务有互相的依赖性,可以考虑使用这种队列。

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
  1. 无界队列(Unbounded Queue)
    比如:LinkedBlockingQueue
    可以理解为如果有任务需要入队列,那么总会入队成功。
    因此按照创建新线程的条件,理论上不会有超过corePoolSize个数的线程。也就是说理论上线程数最多为corePoolSize,因此maxPoolSize的设置也就显得没有意义了。如果提交的任务互相间没有依赖性,可以考虑使用这种队列
  2. 有界队列(Bounded Queue)
    比如:ArrayBlockingQueue
    如果使用有限个maxPoolSize,那么使用这种队列可以防止资源的耗尽。
    使用长队列和小的线程池,可以降低CPU使用率,降低系统资源的消耗,以及降低线程上下文切换的消耗,但是会导致低吞吐量。如果任务频繁的阻塞,系统可能会创建比允许的线程数多的线程。
    使用短队列和大的线程池,可以提高CPU使用率,但也有可能导致吞吐量下降。

threadFactory 线程工程,用来创建线程

handler 拒绝策略,当线程池已经满的时候再添加新的线程进来以什么方式进行处理,目前提供了四种

上一篇 下一篇

猜你喜欢

热点阅读