• Java线程池ExecutorService和Executors应用(Spring Boot微服务)


    记录:476

    场景:在Spring Boot微服务中使用ExecutorService管理Java线程池。使用Executors创建线程池。使用Runnable接口实现类提交线程任务到线程池执行。

    版本:JDK 1.8,Spring Boot 2.6.3。

    1.线程和线程池基础

    JDK自带线程和线程池包位置:java.util.concurrent.*,以及java.lang.Runnable和java.lang.Thread在java.lang.*中。

    1.1线程接口Runnable

    接口全称:java.lang.Runnable。

    接口注释:The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread.

    说明:提交给线程执行的类需实现Runnable接口。该接口只有一个抽象方法public abstract void run()。具体业务逻辑如需被线程调用的话,必须在此run方法内调用业务逻辑。

    1.2线程Thread

    类全称:java.lang.Thread。

    类注释:A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.

    说明:线程java.lang.Thread实现了java.lang.Runnable接口。在java.lang.Thread中维护了JVM中对线程的属性和方法的操作。方法包括线程创建、初始化、启动、运行、停止等。属性包括

    线程名称、优先级、守护进程标志位、线程组、线程本地变量等。

    接收Runnable线程任务方式:一般在创建Thread线程对象时,在有参构造函数的输入参数中传入自定义线程任务(实现Runnable接口的对象)。比如:public Thread(Runnable target)。

    1.3线程池

    (1)接口

    java.util.concurrent.Executor,线程池顶层接口,只有一个抽象方法void execute(Runnable command)。此方法执行提交给线程池已实现Runnable接口的线程任务。

    java.util.concurrent.ExecutorService,线程池接口,实现java.util.concurrent.Executor接口。此接口中主要提供线程池提交任务的submit方法、和invokeAll方法等方法。

    (2)抽象类

    java.util.concurrent.AbstractExecutorService,线程池默认实现方式,在AbstractExecutorService中提供默认的实现ExecutorService接口的方式。

    (3)实现类

    java.util.concurrent.ThreadPoolExecutor,线程池实现类。

    主要是对线程池的创建、运行、维护等方面管理。

    属性包括运行状态、线程池大小、线程池任务数量、线程池工厂类ThreadFactory、线程池工作线程、线程池同步线程锁、线程池任务队列BlockingQueue workQueue等。

    方法包括一序列有参构造函数创建线程池、线程池执行任务方法void execute(Runnable command),以及获取线程池相关属性的get方法和设置线程池相关属性的set方法。

    1.4线程池创建工具类Executors

    全称:java.util.concurrent.Executors。

    说明:在Executors中包括一序列创建线程池的静态方法,此类构造方法是private类型,因此不可被实例化。

    类方法包括如下,可按需选择。

    1. public static ExecutorService newFixedThreadPool(int nThreads);
    2. public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);
    3. public static ExecutorService newWorkStealingPool();
    4. public static ExecutorService newWorkStealingPool(int parallelism)
    5. public static ExecutorService newSingleThreadExecutor();
    6. public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) ;
    7. public static ExecutorService newCachedThreadPool();
    8. public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);
    9. public static ScheduledExecutorService newSingleThreadScheduledExecutor();
    10. public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory);
    11. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
    12. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);

    1.5其它

    (1)线程专用的一些类

    java.lang.Runnable

    java.util.concurrent.Callable

    java.util.concurrent.Future

    java.util.concurrent.FutureTask

    (2)线程工程类

    线程池工厂(接口)

    java.util.concurrent.ThreadFactory

    线程池工厂(实现类)

    java.util.concurrent.Executors.DefaultThreadFactory

    java.util.concurrent.Executors.PrivilegedThreadFactory

    (3)调度类线程体现

    接口

    java.util.concurrent.Executor

    java.util.concurrent.ExecutorService

    java.util.concurrent.ScheduledExecutorService

    实现类

    java.util.concurrent.ThreadPoolExecutor

    实现类

    java.util.concurrent.ScheduledThreadPoolExecutor

    (4)其它

    java.lang.SecurityManager

    java.util.concurrent.ThreadPoolExecutor.Worker

    2.使用Spring Boot注解配置线程池ExecutorService

    (1)说明

    ThreadPoolExecutor,全称:java.util.concurrent.ExecutorService。

    使用@Bean("executorServiceHz")注解把线程池注入到Spring IOC容器中。

    (2)代码

    1. @Configuration
    2. public class ThreadPoolConfig {
    3. /**
    4. * 创建线程池
    5. */
    6. @Bean("executorServiceHz")
    7. public ExecutorService executorService() {
    8. ExecutorService executorService = Executors.newFixedThreadPool(8, new ThreadFactory() {
    9. @Override
    10. public Thread newThread(Runnable runnable) {
    11. return new Thread(runnable);
    12. }
    13. });
    14. return executorService;
    15. }
    16. }

    3.实现Runnable接口的线程任务类

    (1)说明

    提交给线程池任务,需实现Runnable接口。

    Runnable接口的run方法里面就是线程具体执行的业务逻辑。

    (2)代码

    1. public class SportContestExecutor implements Runnable {
    2. private TaskDto taskDto;
    3. public SportContestExecutor(TaskDto taskDto) {
    4. this.taskDto = taskDto;
    5. }
    6. @Override
    7. public void run() {
    8. String eventName = this.taskDto.getEventName();
    9. String content = this.taskDto.getContent();
    10. System.out.println("【线程: " + Thread.currentThread().getName() + ",在直播: " + eventName + content + "】");
    11. }
    12. }

    4.把实现Runnable接口的线程任务类提交到线程池

    (1)说明

    Runnable接口的线程任务类需提交到线程池才能具体执行。

    (2)代码

    1. @Component("sportWorker02")
    2. public class SportWorker02 {
    3. /**
    4. * 自动注入线程池
    5. */
    6. @Autowired
    7. private ExecutorService executorServiceHz;
    8. /**
    9. * 把线程任务提交到线程池
    10. */
    11. public void holdGame() {
    12. //1.准备数据
    13. List groupStage = new ArrayList<>();
    14. for (int i = 0; i < 10; i++) {
    15. String no = "" + (i + 1);
    16. if (i < 9) {
    17. no = "0" + (i + 1);
    18. }
    19. TaskDto taskDto01 = TaskDto.builder().eventName("羽毛球球比赛").content("小组赛" + no).build();
    20. groupStage.add(taskDto01);
    21. }
    22. //2.线程任务提交到线程池
    23. for (TaskDto taskDto : groupStage) {
    24. executorServiceHz.execute(new SportContestExecutor(taskDto));
    25. }
    26. }
    27. }

    5.测试示例

    (1)说明

    直接在SpringBoot的启动类的main函数中测试。

    在执行完成SpringApplication.run(Example212Application.class)后,SpringBoot的环境已经创建完成。

    (2)代码

    1. @SpringBootApplication
    2. public class Example212Application {
    3. public static void main(String[] args) {
    4. SpringApplication.run(Example212Application.class);
    5. SportWorker02 sportWorker02 = SpringUtil.getBean("sportWorker02");
    6. sportWorker02.holdGame();
    7. }
    8. }

    (3)输出结果

    1. 【线程: Thread-5,在直播: 羽毛球球比赛小组赛02
    2. 【线程: Thread-4,在直播: 羽毛球球比赛小组赛01
    3. 【线程: Thread-6,在直播: 羽毛球球比赛小组赛03
    4. 【线程: Thread-7,在直播: 羽毛球球比赛小组赛04
    5. 【线程: Thread-8,在直播: 羽毛球球比赛小组赛05
    6. 【线程: Thread-7,在直播: 羽毛球球比赛小组赛09】
    7. 【线程: Thread-5,在直播: 羽毛球球比赛小组赛10
    8. 【线程: Thread-10,在直播: 羽毛球球比赛小组赛07
    9. 【线程: Thread-9,在直播: 羽毛球球比赛小组赛06
    10. 【线程: Thread-11,在直播: 羽毛球球比赛小组赛08】

    6.辅助实体类

    (1)说明

    在实体类中使用注解@Data等来自lombok-1.18.24.jar。

    (2)TaskDto

    1. @Data
    2. @Builder
    3. @AllArgsConstructor
    4. @NoArgsConstructor
    5. public class TaskDto implements Serializable {
    6. //赛事名称
    7. private String eventName;
    8. //活动内容
    9. private String content;
    10. }

    以上,感谢。

    2023年9月14日

  • 相关阅读:
    STM32开发(三十一)STM32F103 片内资源 —— 模拟/数字转换 DAC 正弦波 编程详解
    部署Redis集群
    《猪猪1984》NFT 作品集将上线 The Sandbox 市场平台
    DataGridXL 2.0 for JavaScript Crack
    Python的命名规范,还是要了解一下的
    如何使用ArcGIS Pro制作个性三维地形图
    Linux学习第13天:嵌入式LinuxLED驱动开发:一字一符总见情
    深入理解RocketMQ 广播消费
    Redis 分布式锁
    Android自定义注解实现一键校验实体类参数
  • 原文地址:https://blog.csdn.net/zhangbeizhen18/article/details/132890256