首页 > 编程语言 >并发编程/6种线程池设计图/1大线程池标准设计与执行规范/2种线程池管理设计(全面篇)

并发编程/6种线程池设计图/1大线程池标准设计与执行规范/2种线程池管理设计(全面篇)

时间:2024-11-07 18:45:11浏览次数:5  
标签:ExecutorService 队列 设计图 任务 线程 设计 执行 ThreadPoolExecutor

在这里插入图片描述

在现代多核处理器时代,线程池成为了并发编程中不可或缺的工具,它不仅提高了程序性能,还简化了线程管理。线程池允许我们重用有限数量的线程来执行大量任务,从而减少了线程创建和销毁的开销。Java中的ExecutorService接口及其实现类,如FixedThreadPoolSingleThreadExecutorCachedThreadPoolScheduledThreadPool,提供了强大的线程池管理功能。这些线程池通过智能地调度任务和复用线程,帮助我们优化资源利用,提高响应速度,并处理复杂的并发场景。对于Java开发者而言,理解线程池的工作原理和正确选择适当的线程池类型对于构建高效、可伸缩的并发应用至关重要。

肖哥弹架构 跟大家“弹弹” 高并发锁, 关注公号回复 ‘mvcc’ 获得手写数据库事务代码

欢迎 点赞,关注,评论。

关注公号Solomon肖哥弹架构获取更多精彩内容

历史热点文章

1、线程池工作流程

在这里插入图片描述

  1. ExecutorService:这是线程池的管理接口,负责提交任务和管理工作线程。
  2. 任务队列(Task Queue) :这是一个先进先出(FIFO)的队列,用于存储待执行的任务。
  3. 线程池(Thread Pool) :这是一组工作线程的集合,它们从任务队列中取出任务并执行。
  4. 工作线程(Worker Thread) :线程池中的每个线程都会循环地从任务队列中取出任务并执行。
  5. 任务(Task) :这是需要执行的具体任务,可以是 RunnableCallable 对象。
  6. 返回结果(Return Result) :任务执行完成后,会返回结果或异常信息。

2、ExecutorService 设计本质

  1. 线程生命周期管理
    • 在Java 5之前,开发者需要手动管理线程的创建和销毁,这不仅增加了编程复杂性,还可能导致资源浪费和系统开销。ExecutorService 通过提供线程池管理功能,简化了线程的生命周期管理。
  2. 系统开销降低
    • 频繁地创建和销毁线程会导致性能问题和资源消耗。ExecutorService 允许线程池重用线程,从而降低了系统开销。
  3. 资源利用率提升
    • 通过线程池复用线程,ExecutorService 提高了资源利用率和程序响应速度,使得多线程编程更加灵活和高效。
  4. 丰富的任务调度和并发控制
    • ExecutorService 提供了丰富的任务调度和并发控制能力,使得多线程编程更加灵活和高效。
  5. 硬件发展推动
    • 随着多核架构的出现,Java的设计者们决定重新修订Java的内存模型,并在JDK1.5中引入了java.util.concurrent包,其中就包括了ExecutorService接口,以支持更高效的并行计算。
  6. 简化并发编程
    • ExecutorService 作为Java并发编程的重要工具,简化了并发编程的复杂性,使得开发者可以更容易地实现并行处理和任务调度。
  7. 提高程序性能
    • ExecutorService 通过减少线程创建和销毁的开销,提高了程序的性能和可伸缩性。
  8. 线程池的易用性
    • Executors 类提供了便捷的工厂方法来创建不同类型的线程池,使得开发者无需手动实现复杂的线程池逻辑,就可以方便地使用线程池。

3、线程池类设计

在这里插入图片描述

在这个类设计图中,我们有以下组件:

  • ExecutorService:这是一个接口,定义了线程池管理的方法,如 submitinvokeAllinvokeAnyshutdown 等。
  • ThreadPoolExecutor:这是 ExecutorService 的一个具体实现,提供了线程池的详细控制,如 executesubmitshutdown 等。
  • ScheduledExecutorService:这是 ExecutorService 的一个子接口,用于延迟执行或定期执行任务。
  • FutureTask:这是 Future 接口的一个实现类,用于封装异步任务,并提供方法如 rungetisDone 等。

4、线程池功能范围设计

4.1. 接口定义

ExecutorService 扩展了 Executor 接口,增加了提交任务后返回 Future 对象的方法,这些方法允许任务异步执行,并提供了获取任务结果的机制。

4.2. 任务提交
  • submit(Callable<T> task): 提交一个返回结果的任务,并返回一个 Future 对象。
  • submit(Runnable task): 提交一个不返回结果的任务,并返回一个 Future 对象。
  • submit(Runnable task, T result): 提交一个不返回结果的任务,并返回一个已经设置好结果的 Future 对象。
4.3. 批量任务执行
  • invokeAll(Collection<? extends Callable<T>> tasks): 提交一个任务集合,等待所有任务完成,并返回每个任务结果的列表。
  • invokeAny(Collection<? extends Callable<T>> tasks): 提交一个任务集合,等待任意一个任务完成,并返回该任务的结果。
4.4. 线程池管理
  • shutdown(): 启动一次有序的关闭,执行已提交的任务,不接受新任务。
  • shutdownNow(): 尝试停止所有正在执行的任务,并返回未执行任务的列表。
  • awaitTermination(long timeout, TimeUnit unit): 等待直到所有任务完成或超时。
4.5. 线程生命周期

ExecutorService 允许线程的复用,减少了线程创建和销毁的开销。线程池可以根据需要创建新线程或重用空闲线程。

4.6. 线程池的可扩展性

ExecutorService 可以与不同的线程池实现一起工作,如 FixedThreadPoolCachedThreadPoolScheduledThreadPool 等,提供了高度的可扩展性和灵活性。

4.7. 异常处理

ExecutorService 提交的任务如果抛出异常,可以通过 Future 对象的 get 方法捕获这些异常。

4.8. 结果处理

Future 对象提供了 get 方法来获取任务结果,如果任务尚未完成,get 方法会阻塞直到任务完成。

4.9. 任务取消

Future 对象提供了 cancel 方法来取消任务,可以传入一个布尔值参数来决定是否中断正在执行的任务。

4.10. 线程工厂和拒绝策略

ExecutorService 可以使用自定义的线程工厂来创建线程,以及自定义的拒绝策略来处理任务提交过多时的情况。
ExecutorService 的设计提供了一个强大的框架,用于构建并发应用程序,它简化了并发编程的复杂性,同时提供了丰富的控制和灵活的配置选项。通过 ExecutorService,开发者可以更容易地实现线程安全的异步任务执行。

5、线程池的种类

  1. FixedThreadPool

    • 拥有固定数量线程的线程池,适用于负载较重的服务器。
      在这里插入图片描述
  2. SingleThreadExecutor

    • 只有一个线程的线程池,用于顺序执行任务。
      在这里插入图片描述
  3. CachedThreadPool

    • 根据需要创建新线程的线程池,对于短生命周期的异步任务非常合适。
      在这里插入图片描述
  4. ScheduledThreadPool

    • 用于延迟执行或定期执行任务的线程池。
      在这里插入图片描述
  5. SingleThreadScheduledExecutor

    • 单个线程的变体,用于延迟或定时执行任务。
      在这里插入图片描述
  6. WorkStealingPool

    • 基于工作窃取算法的线程池,适用于并行计算。
      在这里插入图片描述

这些线程池都是通过Executors工具类提供的工厂方法来创建的。除了这些,开发者还可以通过直接实例化ThreadPoolExecutor类来创建自定义配置的线程池。

ExecutorService接口本身并不定义线程池的具体实现,而是提供了一组通用的接口,用于管理和执行异步任务。不同的线程池实现提供了不同的功能和性能特性,以适应不同的并发场景。

6、ThreadPoolExecutor 线程池设计

简化版
在这里插入图片描述

  1. 核心参数初始化:包括核心线程数、最大线程数、任务队列、空闲线程存活时间和线程工厂等参数的初始化。
  2. 任务提交到线程池:当任务被提交到线程池时,线程池会根据当前的状态和参数来决定如何处理这个任务。
  3. 线程获取任务并执行:如果有空闲的核心线程,它会直接执行任务;如果没有空闲的核心线程但任务队列未满,任务会被添加到任务队列中。
  4. 创建非核心线程执行任务:如果任务队列已满且当前线程数小于最大线程数,会创建一个新的非核心线程来执行任务。
  5. 拒绝策略处理任务:如果任务队列已满且线程数达到最大线程数,任务将被拒绝,线程池会根据拒绝策略处理器来处理这个任务。
  6. 线程池状态管理ThreadPoolExecutor 维护一个 ctl 变量,用于控制线程池的状态,包括 RUNNING、SHUTDOWN、STOP、TIDYING 和 TERMINATED 等状态。

详细版
在这里插入图片描述

  1. 创建 ThreadPoolExecutor:创建一个 ThreadPoolExecutor 实例,开始线程池的初始化过程。
  2. 核心参数初始化:初始化线程池的核心参数,包括核心线程数、最大线程数、任务队列、空闲线程存活时间和线程工厂。
  3. 任务提交到线程池:当任务被提交到线程池时,线程池会根据当前的状态和参数来决定如何处理这个任务。
  4. 线程获取任务并执行:如果有空闲的核心线程,它会直接执行任务;如果没有空闲的核心线程但任务队列未满,任务会被添加到任务队列中。
  5. 创建非核心线程执行任务:如果任务队列已满且当前线程数小于最大线程数,会创建一个新的非核心线程来执行任务。
  6. 拒绝策略处理任务:如果任务队列已满且线程数达到最大线程数,任务将被拒绝,线程池会根据拒绝策略处理器来处理这个任务。
  7. 线程尝试获取新任务:任务执行完毕后,线程会尝试从任务队列中获取新的任务。
  8. 线程销毁或等待新任务:如果任务队列空,线程会进入空闲状态,如果达到空闲线程存活时间,线程将被销毁。
  9. 线程池状态检查:线程池会根据其状态来决定是否停止接收新任务,是否中断运行中的任务,以及是否等待线程终止。
6.1 ThreadPoolExecutor应用
6.1.1. 服务器端处理请求

在服务器应用中,ThreadPoolExecutor 可以用来处理客户端的请求。服务器可以创建一个固定大小的线程池来同时处理多个请求,提高响应速度和吞吐量。

int corePoolSize = 10; // 核心线程数
int maximumPoolSize = 50; // 最大线程数
long keepAliveTime = 120; // 空闲线程存活时间
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100); // 任务队列

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    unit,
    workQueue
);

// 提交任务到线程池
executor.execute(new ClientRequestHandler());
6.1.2. 批量数据处理

在处理批量数据时,如文件处理或数据库批量操作,ThreadPoolExecutor 可以用来并行处理数据,提高处理速度。

List<Data> dataList = ...; // 待处理的数据列表
int threadCount = Runtime.getRuntime().availableProcessors(); // 使用可用处理器数量作为线程数

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    threadCount,
    threadCount,
    0L,
    TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<>()
);

dataList.forEach(data -> executor.execute(new DataProcessorTask(data)));
6.1.3. 异步任务执行

在需要异步执行任务的场景中,ThreadPoolExecutor 可以用来提交任务并在未来某个时刻获取结果。

Future<String> future = executor.submit(() -> {
    // 异步执行的任务
    return "任务结果";
});

// 获取异步任务的结果
String result = future.get();
6.1.4. 定时和周期性任务

ThreadPoolExecutor 可以与 ScheduledExecutorService 结合使用,来执行定时和周期性任务。

ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1);

scheduledExecutor.scheduleAtFixedRate(() -> {
    // 定时执行的任务
}, 0, 10, TimeUnit.SECONDS);
6.1.5. 资源受限环境下的任务处理

在资源受限的环境中,如移动设备或嵌入式系统,ThreadPoolExecutor 可以用来合理分配有限的计算资源。

int maxThreads = 4; // 根据设备性能设置最大线程数

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    maxThreads,
    maxThreads,
    60L,
    TimeUnit.SECONDS,
    new SynchronousQueue<>()
);

7、ScheduledExecutorService 线程池设计

在这里插入图片描述

  1. ScheduledExecutorService:这是线程池的管理接口,负责提交和管理任务。
  2. 任务队列(Task Queue) :这是一个延迟队列,用于存储待执行的任务,按照预定的执行时间排序。
  3. 核心线程池(Core Thread Pool) :线程池中的核心线程会不断地从任务队列中取出任务并执行。
  4. 工作线程(Worker Thread) :线程池中的线程负责执行任务。
  5. 执行周期性任务(scheduleAtFixedRate) :用于安排任务以固定频率执行。
  6. 执行延迟任务(scheduleWithFixedDelay) :用于安排任务在每次执行完毕后按照固定延迟执行。
  7. 执行单次任务(schedule) :用于安排任务在指定延迟后执行一次。
  8. 任务完成:任务执行完毕后,如果是周期性任务,会重新调度下一次执行。
  9. 线程池关闭(Thread Pool Shutdown) :当不再需要线程池时,可以关闭线程池,等待所有任务完成或尝试立即停止所有任务。
7.1ScheduledExecutorService应用案例
7.1.1. 一次性延迟执行任务

在这个例子中,我们创建了一个 ScheduledExecutorService 实例,并安排了一个任务在延迟一定时间后执行。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DelayedTaskExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        Runnable task = () -> System.out.println("任务在延迟后执行:" + System.currentTimeMillis());
        scheduler.schedule(task, 5, TimeUnit.SECONDS); // 5秒后执行
        scheduler.shutdown(); // 执行完毕后关闭调度器
    }
}
7.1.2. 固定速率周期执行任务

在这个例子中,我们安排了一个任务以固定的速率周期性执行。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class FixedRateTaskExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        Runnable task = () -> System.out.println("定期任务执行时间: " + System.currentTimeMillis());
        scheduler.scheduleAtFixedRate(task, 0, 10, TimeUnit.SECONDS); // 每10秒执行一次
        scheduler.shutdown(); // 执行完毕后关闭调度器
    }
}
7.1.3. 固定延迟周期执行任务

在这个例子中,我们安排了一个任务在每次执行完毕后,等待固定的延迟时间再执行下一次。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class FixedDelayTaskExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        Runnable task = () -> System.out.println("带有固定延迟的任务执行时间: " + System.currentTimeMillis());
        scheduler.scheduleWithFixedDelay(task, 0, 15, TimeUnit.SECONDS); // 每次执行完毕后等待15秒再执行
        scheduler.shutdown(); // 执行完毕后关闭调度器
    }
}

标签:ExecutorService,队列,设计图,任务,线程,设计,执行,ThreadPoolExecutor
From: https://blog.csdn.net/alises1314/article/details/143567267

相关文章

  • 【拯救大学生毕业设计】基于springboot的月度员工绩效考核管理系统
    本项目开发文档(带文档lw万字以上)已上传审核中。源码亲测可用!!!点击文末名片获取获取全部源码以及个性化部署定制服务摘 要科学时代的发展改变了人类的生活,促使网络与计算机技术深入人类的各个角落,得以普及到人类的具体生活中,为人类的时代文明掀开新的篇章。本系统为月......
  • 基于nodejs+vue在线音乐网站[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于在线音乐网站的研究,现有研究多侧重于音乐推荐算法、版权管理等方面3。专门针对在线音乐网站整体功能架构,包括用户、歌手分类、歌曲信息等综合系统功......
  • 基于nodejs+vue在线音乐播放平台[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于在线音乐播放平台的研究,现有研究主要集中在大型商业音乐平台的整体运营、用户体验优化等方面,如QQ音乐、网易云音乐等平台的功能拓展、营销策略等。......
  • 基于JAVA的在线购物平台设计与实现-计算机毕设 附源码 26720
    基于JAVA的在线购物平台设计与实现摘要基于JAVA的在线购物平台设计与实现是一个涉及到软件开发和电子商务的综合课题。在这样的平台上,用户可以浏览商品、将商品加入购物车、进行下单购买等操作。为了实现这一功能,需要考虑到前后端的交互、数据库的设计、安全性和用户体......
  • 【Java深度揭秘】掌握SPI机制,让你的代码设计更优雅!
    SPI(ServiceProviderInterface)机制是Java中一种服务发现和加载的机制,它允许第三方为应用程序提供实现。SPI机制广泛应用于Java标准库以及各种框架中,如JDBC、JNDI等。SPI机制的基本概念接口定义:首先定义一个接口,这个接口规定了服务提供者需要实现的方法。配置文件:在META-INF/......
  • 线程的概念、作用和属性
    线程的概念、作用和属性线程的概念理解:线程可视作“轻量级进程”。线程是一个基本的CPU执行单元,也是程序执行流的最小单位。引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如QQ视频、文......
  • 线程的实现方式和多线程模型
    线程的实现方式和多线程模型‍​​‍一、线程的实现方式(一)用户级线程​​‍(二)内核级线程​​‍二、多线程模型在支持内核级线程的系统中,根据用户级线程和内核级线程的映射关系,可以划分不同的多线程模型(一)一对一模型​​‍(二)多对一模型和上面提到的用户级线程的......
  • 软件设计师:排序算法总结
    一、直接插入排序方式:从第一个数开始,拿两个数比较,把后面一位跟前面的数比较,把较小的数放在前面一位二、希尔排序方式:按“增量序列(步长)”分组比较,组内元素比较交换 假设初始关键字:48   37   64   96   75   12   26   58   54   3,有......
  • 部分硬件电路设计记录备忘
    1、静电和浪涌保护(TVS/ESD)首先,TVS\钳位二极管\瞬态抑制二极管,可以看做是一种东西,只是称呼不同。然后就是,TVS防护包含两部分:静电释放(ESD)和浪涌(Surge),TVS参数不同,防护侧重也不同。ESD和Surge的主要区别:频率不一样,ESD高频,Surge低频。【1】静电:不用多说了。。。【2】浪涌:......
  • 有刷无线充气泵打气筒方案电路设计
    电动充气泵方案基于简单原理,使用时能自动检测轮胎压力。当胎压低于预设值时,电机自动启动,将压缩气体经进气管泵入轮胎。一旦充气泵达到设定的胎压上限,电机将自动关闭。该方案由压力传感器、ADC芯片、主控芯片等核心组件构成。其关键功能参数如下:显示方式:采用LED/LCD显示屏,实现......