• Java线程池ThreadPoolExecutor应用(Spring Boot微服务)


    记录:475

    场景:在Spring Boot微服务中使用Java线程池ThreadPoolExecutor。实现Runnable接口提交线程任务到线程池。

    版本:JDK 1.8,Spring Boot 2.6.3。

    1.使用注解配置线程池ThreadPoolExecutor

    (1)说明

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

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

    (2)代码

    1. @Configuration
    2. public class ThreadPoolConfig {
    3. @Bean("threadPoolExecutorHz")
    4. public ThreadPoolExecutor threadPoolExecutor(){
    5. ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
    6. 8,
    7. 16,
    8. 10,
    9. TimeUnit.MILLISECONDS,
    10. new ArrayBlockingQueue(10),
    11. new ThreadPoolExecutor.CallerRunsPolicy()
    12. );
    13. return threadPoolExecutor;
    14. }
    15. }

    (3)线程参数

    corePoolSize: the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set

    maximumPoolSize: the maximum number of threads to allow in the pool

    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.

    unit: the time unit for the keepAliveTime argument

    workQueue: the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.

    handler: the handler to use when execution is blocked because the thread bounds and queue capacities are reached

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

    (1)说明

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

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

    (2)代码

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

    3.线程具体业务逻辑类

    (1)说明

    本例线程执行的业务逻辑实现类均继承于同一个抽象类。因此,在Runnable接口的线程任务类中是基于抽象类编程。

    (2)抽象类SportContest

    全称:com.hub.example.p1.contest.SportContest

    代码:

    1. public abstract class SportContest {
    2. //赛事任务
    3. private TaskDto taskDto;
    4. //开场仪式
    5. public abstract String announceStart();
    6. //举行比赛
    7. public abstract ResultDto playGame();
    8. //颁奖仪式
    9. public abstract String announceEnd(ResultDto resultDto);
    10. //举行体育赛事
    11. public String holdSportGame() {
    12. String result01 = announceStart();
    13. ResultDto result02 = playGame();
    14. String result03 = announceEnd(result02);
    15. return result03;
    16. }
    17. public TaskDto getTaskDto() {
    18. return taskDto;
    19. }
    20. public void setTaskDto(TaskDto taskDto) {
    21. this.taskDto = taskDto;
    22. }
    23. }

    (3)实现类BadmintonContest

    全称:com.hub.example.p1.contest.impl.BadmintonContest

    代码:

    1. public class BadmintonContest extends SportContest {
    2. public BadmintonContest(TaskDto taskDto){
    3. this.setTaskDto(taskDto);
    4. }
    5. @Override
    6. public String announceStart() {
    7. TaskDto taskDto = this.getTaskDto();
    8. System.out.println("举行羽毛球比赛入场仪式:");
    9. System.out.println("羽毛球比赛入场仪式步骤一: "+taskDto.getEventName()+"队员入场.");
    10. System.out.println("羽毛球比赛入场仪式步骤二: 裁判员、教练员等各就各位.");
    11. return "羽毛球比赛进行中";
    12. }
    13. @Override
    14. public ResultDto playGame() {
    15. TaskDto taskDto = this.getTaskDto();
    16. System.out.println("举行羽毛球比赛: "+taskDto.getContent()+",选手们在奋力搏击.");
    17. return ResultDto.builder().teamName("中国羽毛球队").content("男单决赛冠军").build();
    18. }
    19. @Override
    20. public String announceEnd(ResultDto resultDto) {
    21. System.out.println("举行羽毛球比赛颁奖仪式: ");
    22. System.out.println("羽毛球比赛颁奖步骤一: 为"+resultDto.getTeamName()+resultDto.getContent()+"颁发金牌.");
    23. System.out.println("羽毛球比赛颁奖步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.");
    24. return "羽毛球比赛圆满结束";
    25. }
    26. }

    (4)实现类DivingContest

    全称:com.hub.example.p1.contest.impl.BadmintonContest

    代码:

    1. public class DivingContest extends SportContest {
    2. public DivingContest(TaskDto taskDto) {
    3. this.setTaskDto(taskDto);
    4. }
    5. @Override
    6. public String announceStart() {
    7. TaskDto taskDto = this.getTaskDto();
    8. System.out.println("举行跳水比赛入场仪式:");
    9. System.out.println("跳水比赛入场仪式步骤一: "+taskDto.getEventName()+"队员入场.");
    10. System.out.println("跳水比赛入场仪式骤二: 裁判员、教练员等各就各位.");
    11. return "跳水比赛进行中";
    12. }
    13. @Override
    14. public ResultDto playGame() {
    15. TaskDto taskDto = this.getTaskDto();
    16. System.out.println("举行跳水比赛: " + taskDto.getContent() + ",姑娘们在冲刺记录.");
    17. return ResultDto.builder().teamName("中国跳水队").content("女子10米台跳板决赛冠军").build();
    18. }
    19. @Override
    20. public String announceEnd(ResultDto resultDto) {
    21. System.out.println("跳水比赛举行颁奖仪式: ");
    22. System.out.println("跳水比赛举行颁奖仪式步骤一: 为"+resultDto.getTeamName()+resultDto.getContent()+"颁发金牌.");
    23. System.out.println("跳水比赛举行颁奖仪式步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.");
    24. return "跳水比赛圆满结束";
    25. }
    26. }

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

    (1)说明

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

    (2)代码

    1. @Component("sportWorker01")
    2. public class SportWorker01 {
    3. /**
    4. * 自动注入线程池
    5. * */
    6. @Autowired
    7. private ThreadPoolExecutor threadPoolExecutor;
    8. /**
    9. * 把线程任务提交到线程池
    10. */
    11. public void holdGame() {
    12. SportContest tableTennis = createBean("com.hub.example.p1.contest.impl.BadmintonContest",
    13. TaskDto.builder().eventName("羽毛球球比赛").content("男单决赛").build());
    14. SportContestExecutor executor01= new SportContestExecutor(tableTennis);
    15. SportContest swimming = createBean("com.hub.example.p1.contest.impl.DivingContest",
    16. TaskDto.builder().eventName("跳水比赛").content("女子10米台跳板决赛").build());
    17. SportContestExecutor executor02= new SportContestExecutor(swimming);
    18. threadPoolExecutor.execute(executor01);
    19. ThreadUtil.sleep(1000);
    20. threadPoolExecutor.execute(executor02);
    21. }
    22. /**
    23. * 使用Java反射方式创建对象
    24. */
    25. public SportContest createBean(String className, TaskDto params) {
    26. try {
    27. Class clazz = Class.forName(className);
    28. Constructor constructor = clazz.getConstructor(TaskDto.class);
    29. SportContest sportContest = (SportContest) constructor.newInstance(params);
    30. return sportContest;
    31. } catch (Exception e) {
    32. return null;
    33. }
    34. }
    35. }

    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. SportWorker01 sportWorker01 = SpringUtil.getBean("sportWorker01");
    6. sportWorker01.holdGame();
    7. }
    8. }

    (3)输出结果

    1. 【线程: pool-1-thread-1,在直播: 羽毛球球比赛】
    2. 举行羽毛球比赛入场仪式:
    3. 羽毛球比赛入场仪式步骤一: 羽毛球球比赛队员入场.
    4. 羽毛球比赛入场仪式步骤二: 裁判员、教练员等各就各位.
    5. 举行羽毛球比赛: 男单决赛,选手们在奋力搏击.
    6. 举行羽毛球比赛颁奖仪式:
    7. 羽毛球比赛颁奖步骤一: 为中国羽毛球队男单决赛冠军颁发金牌.
    8. 羽毛球比赛颁奖步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.
    9. 【线程: pool-1-thread-2,在直播: 跳水比赛】
    10. 举行跳水比赛入场仪式:
    11. 跳水比赛入场仪式步骤一: 跳水比赛队员入场.
    12. 跳水比赛入场仪式骤二: 裁判员、教练员等各就各位.
    13. 举行跳水比赛: 女子10米台跳板决赛,姑娘们在冲刺记录.
    14. 跳水比赛举行颁奖仪式:
    15. 跳水比赛举行颁奖仪式步骤一: 为中国跳水队女子10米台跳板决赛冠军颁发金牌.
    16. 跳水比赛举行颁奖仪式步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.

    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. }

    (3)ResultDto

    1. @Data
    2. @Builder
    3. @AllArgsConstructor
    4. @NoArgsConstructor
    5. public class ResultDto implements Serializable {
    6. //竞赛队伍
    7. private String teamName;
    8. //比赛成绩
    9. private String content;
    10. }

    以上,感谢。

    2023年9月13日

  • 相关阅读:
    SQL练习
    微信小程序源码获取(附工具的下载)
    前端性能-首次加载优化70%
    java基础16 GUI编程(Swing和AWT)
    CRM系统中联系人管理的十大好处
    年年出妖事,一例由JSON解析导致的"薛定谔BUG"排查过程记录
    linux文件查看和文件查找
    Node.js | 你不知道的 express 路由使用技巧
    C++智能指针
    【JavaWeb】之Cookie & Session
  • 原文地址:https://blog.csdn.net/zhangbeizhen18/article/details/132867498