JAVA多线程(十八)Java多线程之Executor框架&ThreadPoolExecutor类

1.JAVA多线程(十八)Java多线程之Executor框架&ThreadPoolExecutor类   Executor 框架是 Java5 之后引进的,在 Java 5 之后,通过 Executor 来启动线程比使用 Thread 的 start 方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免 this 逃逸问题。this 逃逸是指在构...
摘要由CSDN通过智能技术生成

1.JAVA多线程(十八)Java多线程之Executor框架&ThreadPoolExecutor类

   Executor 框架是 Java5 之后引进的,在 Java 5 之后,通过 Executor 来启动线程比使用 Thread 的 start 方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免 this 逃逸问题。

this 逃逸是指在构造函数返回之前其他线程就持有该对象的引用. 调用尚未构造完全的对象的方法可能引发令人疑惑的错误。

在开发中如果需要创建线程可优先考虑使用Executor,无论你需要多线程还是单线程,Executor为你提供了很多其他功能,包括线程状态,生命周期的管理。Executor 框架不仅包括了线程池的管理,还提供了线程工厂、队列以及拒绝策略等,Executor 框架让并发编程变得更加简单。

1.1 无限制创建线程不足

   在生产环境中,“为每个任务分配一个线程”这种方法存在一些缺陷,尤其是当需要创建大量线程时:

  1. 管理线程的生命周期开销非常高:管理这些线程的生命周期会明显增加 CPU 的执行时间,会消耗大量计算资源。
  2. 资源消耗:活跃的线程会消耗系统资源,尤其是内存。如果可运行的线程数量多于可用的处理器的数量,那么有些线程将闲置。大量空闲的线程会占用许多内存,给垃圾回收器带来压力,而且大量线程在竞争CPU资源时还将产生其他的性能开销。如果你已经拥有足够多的线程使所有的CPU保持忙碌状态,那么再创建更多的线程反而会降低性能。
  3. 稳定性:创建线程的数量存在一个限制,这个限制将随着平台的不同而不同,并且受多个因素制约,包括jvm的启动参数、Thread构造函数中请求的栈大小,以及底层操作的限制等。如果超过了这个限制,那么很可能抛出OutOfMemoryError异常,这对于运行中的应用来说是非常危险的。

所有的这些因素都会导致系统吞吐量下降。线程池通过保持一些存活线程并重用这些线程来克服这个问题。当提交到线程池中的任务多于线程池最大任务数时,那些多余的任务将被放到一个队列中。 一旦正在执行的线程有空闲了,它们会从队列中取下一个任务来执行。JDK 中的 Executors中, 此任务队列是没有长度限制的。

1.2 Executor的实现关系图

Executor框架包括3大部分:

  • 任务:包括被执行的任务需要实现的接口:Runable 接口、Callable接口;Runnable 接口或 Callable 接口 实现类都可以被 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行。
  • 任务的执行:包括任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口。Executor框架有两个关键类实现了ExecutorService接口:ThreadPoolExecutor 和 ScheduledThreadPoolExecutor、ForkJoinPool;这里提了很多底层的类关系,但是,实际上我们需要更多关注的是 ThreadPoolExecutor 这个类,这个类在我们实际使用线程池的过程中,使用频率还是非常高的。
  • 任务的异步计算结果:包括Future接口和实现Future接口的FutureTask类、ForkJoinTask类,都可以代表异步计算的结果。当我们把 Runnable接口 或 Callable 接口 的实现类提交给 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行。(调用 submit() 方法时会返回一个 FutureTask 对象)

Java优秀框架的设计思路,顶级接口-次级接口-虚拟实现类-实现类。
在这里插入图片描述

属性 说明
Executor 执行者,java线程池框架的最上层父接口,地位类似于spring的BeanFactry、集合框架的Collection接口,在Executor这个接口中只有一个execute方法,该方法的作用是向线程池提交任务并执行。
ExecutorService 该接口继承自Executor接口,添加了shutdown、shutdownAll、submit、invokeAll等一系列对线程的操作方法,该接口比较重要,在使用线程池框架的时候,经常用到该接口。
AbstractExecutorService 这是一个抽象类,实现ExecuotrService接口
ThreadPoolExecutor 这是Java线程池最核心的一个类,该类继承自AbstractExecutorService,主要功能是创建线程池,给任务分配线程资源,执行任务。
ScheduledExecutorSerivce 提供了另一种线程池:延迟执行和周期性执行的线程池。
ScheduledThreadPoolExecutor 提供了另一种线程池:延迟执行和周期性执行的线程池。
Executors 这是一个静态工厂类,该类定义了一系列静态工厂方法,通过这些工厂方法可以返回各种不同的线程池。

1.3 ThreadPoolExecutor 类

  1. 线程池实现类 ThreadPoolExecutor 是 Executor 框架最核心的类。

    ThreadPoolExecutor 类中提供的四个构造方法,直接看参数最多的构造方法,其余三个都是在这个构造方法的基础上产生。源代码如下:
    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @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
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,     // 线程池的核心线程数量,即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut 

                              int maximumPoolSize,  // 池中允许的最大线程数 
                              long keepAliveTime,   // 当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间。 

                              TimeUnit unit,        // keepAliveTime参数的时间单位
                              BlockingQueue<Runnable> workQueue,    // 用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。 
                              ThreadFactory threadFactory,  // 线程工厂,用来创建线程,一般默认即可
                              RejectedExecutionHandler handler // 拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务
                              ) {
   
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值