【并发编程二】线程池Executor创建线程的简单分析

路漫漫其修远兮,吾将上下而求索

线程池的使用

继承Thread类和实现Runnable接口分别提供了单个线程的创建方法,但是线程的创建和销毁是很消耗性能的一种操作,Executor提供了线程池的功能,避免了频繁创建和销毁线程的操作,Executor大体框架如下:

avatar

Executor只是一个基础的接口,其下ThreadPoolExecutor提供了不同的构造方法来创建线程池,以及Executoes提供了不同的静态方法来创建线程池

一、ThreadPoolExecutor分析

(一)、主要参数分析

该类中提供了不同参数的构造方法,最多的构造方法包含七个参数,源码中解释如下:

 @param corePoolSize the number of threads to keep in the pool, even
 *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
 * @param maximumPoolSize the maximum number of threads to allow in the
 *        pool
 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.
 * @param unit the time unit for the {@code keepAliveTime} argument
 * @param workQueue the queue to use for holding tasks before they are
 *        executed.  This queue will hold only the {@code Runnable}
 *        tasks submitted by the {@code execute} method.
 * @param threadFactory the factory to use when the executor
 *        creates a new thread
 * @param handler the handler to use when execution is blocked
 *        because the thread bounds and queue capacities are reached

逐一分析:

1、corePoolSiza(int)

**核心线程数量,**即线程池中要保留的线程数,即使没有任务执行。

2、maxnumPoolSize(int)

**最大线程数,**即线程池中允许的线程的最大数量。

3、keepAliveTime(long)

**保持存活时间,**即当线程池中的线程数量大于corePoolSize时,多出的线程的空闲的最长时间。

4、unit(TimeUnit)

第三个参数即keepAliveTime的时间单位

5、workQueue(BlockingQueue)

队列,即当线程数量小于任务数量时,任务存放的队列,源码中提供了三种策略,分别为SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue;

(1)、SynchronousQueue

该队列下,当任务将任务交给线程如果没有线程可以立即执行任务时,会创建一个新的线程来执行任务,所以该策略通常需要maxnumPoolSize无限制,以避免任务执行失败。

(2)、LinkedBlockingQueue

无界队列(也可自己指定队列大小),在该队列下,当线程池中的corePoolSize数量的线程均在执行任务时,任务会在队列中等待,不会继续创建线程,即maxnumPoolSize不会再起作用。

(3)、ArrayBlockingQueue

有界队列,在该队列下,队列的大小需要和maxnumPoolSize相互协调,当队列size较大而maxnumPoolSize较小时,可能导致任务排队堆积,不能及时处理,而当队列size较小时则需要较大的maxnumPoolSize以防止新任务不能进入队列排队.

6、threadFactory(ThreadFactory)

顾名思义,即当线程池需要创建一个新的线程时使用的工厂。

7、handler(RejectedExecutionHandler)

reject拒绝,当线程池线程数量达到maxnumPoolSize并且队列饱和时,新任务将无法继续排队等待并抛出RejectedExecutionException,该参数即为相应的处理方式。
ThreadPoolExecutor提供了四种(四个内部类)预定的处理策略:

(1)、AbortPolicy

从源码中可见其直接抛出了异常,

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
(2)、CallerRunsPolicy

源码如下:

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }

其调用了Runnable的run()方法,即使用当前线程来执行任务。

(3)、DiscardPolicy

源码如下:

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }

什么都没有做,也就是简单的删除了该任务而已。

(4)、DiscardOldestPolicy

源码如下:

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }

可以看出其将队列头部的元素进行了删除,然后重试执行(可能重复)。

(二)、构造方法分析

ThreadPoolExecutor的构造方法主要是针对以上参数构建,此处不再赘述。

(三)、钩子方法

ThreadPoolExecutor提供了一些钩子方法用于操纵执行环境,如beforeExecute,afterExecute可在任务执行前或执行后做一些操作。terminated()也可以被覆盖重写,以便在程序终止时做一些特殊处理。

二、ScheculedThreadPoolExecutor分析

该类继承了ThreadPoolExrcutor并实现了ScheduleExecutorService接口,官方给的解释是:

该类可以用来调度在给定延迟时间后执行任务或者周期性执行,优选于Timer(只有一个后台线程),可以通过构造函数类指定后台线程个数。

延迟任务的执行时间是没有任何实时保证的,虽然队列遵循先进先出原则,但是线程间是存在竞争关系的。

默认情况下提交的任务在被执行前取消是不会从队列中删除的,可以通过setRemoveOnCancelPolicy(boolean)方法将其从队列中删除。

该类虽然继承了ThreadPoolExecutor,但是其继承的一些调优方法并没有用(通过构造方法来解释) 。

(一)、构造方法详解
1、ScheduledThreadPoolExecutor(int corePoolSize)

源码如下:

 public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

可以看出其相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());

2、ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)

源码如下:

public ScheduledThreadPoolExecutor(int corePoolSize,
                                   ThreadFactory threadFactory) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), threadFactory);
}

即相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory);

3、ScheduledThreadPoolExecutor(int corePoolSize,RejectedExecutionHandler handler)

源码如下:

public ScheduledThreadPoolExecutor(int corePoolSize,
                                   RejectedExecutionHandler handler) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), handler);
}

即相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), handler);

4、ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory,RejectedExecutionHandler handler)

源码如下:

public ScheduledThreadPoolExecutor(int corePoolSize,
                                   ThreadFactory threadFactory,
                                   RejectedExecutionHandler handler) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), threadFactory, handler);
}

即相当于new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory, handler);

**从以上构造方法可以看出,创建SchduledThreadPoolExecutor时只能对corePoolSize,threadFactory,handler三个参数进行操作,所以ThreadPoolExecutor的一些调优方法对于ScheduledThreadPoolExecutor是没有作用的。**另外以上构造方法中均是使用了其内部类DelayedWorkQueue来作为队列对象,以后再分析DelayedWorkQueue吧。

三、Executors分析

Executors提供了一系列创建线程池的静态方法。

(一)、newFixedThreadPool(int nThread)

源码如下:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

相当于创建了一个corePoolSize=maxnumPoolSize的ThreadPoolExecutor对象,队列使用new LinkedBlockingQueue,且默认size为Interger.MAX_VALUE

(二)、newSingleThreadExecutor()

源码如下:

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

相当于创建了一个corePoolSize=maxnumPoolSize=1的ThreadPoolExecutor对象,队列使用new LinkedBlockingQueue,且默认size为Interger.MAX_VALUE

(三)、newCachedThreadPool()

源码如下:

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

创建一个corePoolSize为0,但是maxnumPoolSize为Integer.MZX_VALUE,过期时间为60秒,使用SynchronousQueue做为队列对象的ThreadPoolExecutor。

以上三个静态方法返回对象均ThreadPoolExecutor,只是其参数不同,且均可添加ThreadFactory参数来指定创建线程的工厂。

(四)、ScheduledThreadPool

针对ScheduledThreadPool,Executors提供了以下四种方法:

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}


public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1, threadFactory));
}


public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public static ScheduledExecutorService newScheduledThreadPool(
        int corePoolSize, ThreadFactory threadFactory) {
    return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值