线程池_02_Executor框架

简介:

线程池_02_Executor框架
  • 一、Executor 的两级调度
    • 背景知识
      • 在HotSpot Vm 的线程模型中,Java 线程被一对一映射为本地操作系统线程。Java 线程启动时会创建一个本地操作系统线程;当该Java线程终止时,这个操作系统线程也会被回收。
    • Executor
      • 在上层,Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程;换句话说就是应用程序通过Executor框架控制上层的调度。
      • 在底层,操作系统内核将这些线程映射到硬件处理器上。换句话说,下层的调度由操作系统内核控制,下层的调度不受应用程序的控制。
  • 二、Executor 的组成
    • 1、任务;
      • 包括被执行任务需要实现的接口:Runbable或Callable 接口
    • 2、任务的执行;
      • 包括任务执行机制的核心接口Executor,以及继承自Executor 的ExecutorService接口。Executor 框架有两个关键类实现了ExecutorService 接口
    • 3、异步计算的结果;
      • 包括接口Future 和 实现Future接口的FutureTask类。
  • 三、Executor 使用
    • 1、主线程首先创建Runnable或Callable的任务对象A;
    • 2、然后把对象A直接交给ExecutorService通过Execute或Submit方法执行;
    • 3、如果使用的是submit方法,会返回一个实现Future接口的对象,主线程可以执行FutureTask.get()方法来等待任务执行完成。也可以执行FutureTask.cancle()来取消任务。
  • 四、Executor 主要的类与接口的简介
    • 1、Executor
      • 接口,是Executor框架的基础,它将任务的提交与任务的执行分离开来。
    • 2、ThreadPoolExecutor
      • 线程池的核心实现类,用来执行被提交的任务
    • 3、ScheduledThreadPoolExecutor(定时任务类,这里不讨论)
      • 实现类,可以在给定的延迟后运行命令,或者定期执行命令。
    • 4、Future接口和实现Future接口的FutureTask类,代表异步结算的结果
    • 5、Runnable 和Callable接口的实现类
  • 五、Executor 主要的类与接口的详解
    • ThreadPoolExecutor
      • 四个核心参数:
        • 1、corePool 核心线程池的大小;
        • 2、maximumPool 最大线程池的大小;
        • 3、BlockingQueue 用来暂时保存任务的工作队列;
        • 4、RejectedExecutionHandler 当ThreadPoolExecutor 可以关闭或ThreadExecutor 已经饱和时(达到了最大线程池大小并且工作队列已满),execute()方法将要调用的Handler。
      • ThreadPoolExecutor通常使用工厂类Executors来创建,Executors可以创建3种类型的ThreadPoolExecutor: FixedThreadPool、SingleThreadExecutor、CachedThreadPool;
        • 1、FixedThreadPool ,创建固定线程数的API。
          ac344291-4210-4332-93aa-4b6b753ce0e2-5210562.jpg
          • 创建的方法:
            76f90e81-fae7-483d-9a7d-42cba1d3bc40-5210562.jpg
            • FixedThreadPool 的核心线程和最大线程数是一样的;线程的空闲存活时间为0,则多余的空闲线程会被立即终止。
          • 执行execute(),流程如下:
            • 1、如果当前运行的线程数少于corePoolSize,则创建新线程来执行任务;
            • 2、如果当前运行的线程数等于corePoolSize,将任务加入LinkedBlockingQueue;
            • 3、线程执行完1中的任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行。
          • 使用无界队列LinkedBlockingQueue,影响:
            • 1、如果当前运行的线程数等于corePoolSize,新任务将在无界队列中等待,因此线程池中的线程数不会超过corePoolSize;
            • 2、maximumPoolSize 与 keepAliveTime 会是无效的;
            • 3、运行中的FixedThreadPool 不会拒绝任务(因为工作队列可以无限增大);
        • 2、SingleThreadExecutor,使用单个工作线程的Executor。
          • 创建的方法:
            a097a384-3748-49ac-8e75-cab609957ca5-5210562.jpg
            • 于corePoolSize与maximumPoolSize 设为1,其它参数与FixedThreadPool一样。
          • 执行execute(),流程如下:
            • 1、如果线程池中无运行的线程,则创建一个新线程来执行任务;
            • 2、当前线程池中有一个运行的线程,将任务加入LinkedBlockingQueue;
            • 3、线程执行完1中的任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行。
          • 使用无界队列LinkedBlockingQueue,与FixedThreadPool一样的结果。
        • 3、CachedThreadPool,根据需要创建新线程的线程池。
          • 创建的方法:
            6a95a009-5173-4dad-bdf2-30b8600cf0fc-5210562.jpg
            • corePoolSize 为0,maximumPoolSize被设置为Integer.MAX_VALUE,即是maximumPoolSize无界的。keepAliveTime 设为60秒,空闲存活60秒后被终止。
          • CachedThreadPool 使用没有容量的SynchronousQueue作为线程池的工作队列,但是maximumPoolSize是无界的。这意味着,如果主线程提交任务的速度高于maximumPool中线程处理任务的速度时,CachedThreadPool会不断创建新线程。极端情况下,CachedThreadPool会因为创建过多线程而耗尽CPU和内存资源。
        • 总结:
          • FixedThreadPool 与 SingleThreadExecutor 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而引起OOM异常
          • CachedThreadPool => 允许创建的线程数为Integer.MAX_VALUE,可能会创建大量的线程,从而引起OOM异常
    • FutureTask
      • 使用:
        • 1、由调用线程直接执行FutureTask.run(); ---- 实现了Runnable接口
        • 2、通过ExecutorService.submit()方法返回一个FutureTask; ---- 实现了Future 接口
      • 实现原理
        • 基于AbstractQueuedSynchronizer(简称AQS)。AQS是一个同步框架,它提供通用机制来原子性管理同步状态、阻塞和唤醒线程,以及维护被阻塞线程的队列。
        • 基于AQS实现的同步器包含两种类型:
          • 1、至少一个acquire操作。这个操作阻塞调用线程,除非/直到AQS的状态允许这个线程继续执行。
            • 在FutureTask 类中get()和get(long timeout, TimeUnit unit)两个方法为acquire操作;
          • 2、至少一个release操作。这个操作改变AQS的状态,改变后的状态可允许一个或多个阻塞线程被解除阻塞。
            • 在FutureTask 类中run()和cancel()两个方法为acquire操作;

相关文章
|
4月前
|
并行计算 算法 Java
Java线程池——Executor框架
Executor 框架是 Java5 之后引进的,在 Java 5 之后,通过 Executor 来启动线程比使用 Thread 的 start 方法更好,除了更易管理,效率更好(用线程池实现,节约开销)。 Executor 框架不仅包括了线程池的管理,还提供了线程工厂、队列以及拒绝策略等,Executor 框架让并发编程变得更加简单。
|
6月前
|
存储 Java 调度
【 Executor线程池原理与源码】
【 Executor线程池原理与源码】
|
9月前
|
缓存 监控 Java
为什么要用线程池?简述对线程池的理解。
为什么要用线程池?简述对线程池的理解。
70 0
|
9月前
|
存储 Java C++
ThreadPoolExecutor 线程池执行流程及核心源码分析
ThreadPoolExecutor 线程池执行流程及核心源码分析
64 0
|
11月前
|
存储 缓存 Java
【并发编程】线程池及Executor框架
【并发编程】线程池及Executor框架
|
12月前
|
缓存 Java 调度
JUC系列学习(一):线程池Executor框架及其实现ThreadPoolExecutor
`Executor` 框架将任务的提交与任务的执行**解耦**了。
|
Java
JAVA线程池总结及自定义线程池
JAVA线程池总结及自定义线程池
157 0
|
监控 Java API
Java多线程 线程池Executor框架
Java多线程 线程池Executor框架
134 0
Java多线程 线程池Executor框架
|
存储 缓存 资源调度
Executor框架及线程池总结
Executor作为一个灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程进行了解耦开发,基于生产者和消费者模型,还提供了对生命周期的支持,以及统计信息收集,应用程序管理机制和性能检测等机制。
Executor框架及线程池总结
|
SQL 监控 Java
合理地配置线程池
合理地配置线程池
175 0