记录: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)代码
- @Configuration
- public class ThreadPoolConfig {
- @Bean("threadPoolExecutorHz")
- public ThreadPoolExecutor threadPoolExecutor(){
- ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
- 8,
- 16,
- 10,
- TimeUnit.MILLISECONDS,
- new ArrayBlockingQueue
(10), - new ThreadPoolExecutor.CallerRunsPolicy()
- );
- return threadPoolExecutor;
- }
- }
(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)代码
- public class SportContestExecutor implements Runnable {
- private SportContest sportContest;
- public SportContestExecutor(SportContest sportContest) {
- this.sportContest = sportContest;
- }
- @Override
- public void run() {
- String eventName = sportContest.getTaskDto().getEventName();
- System.out.println("【线程: "+Thread.currentThread().getName()+",在直播: "+eventName+"】");
- this.sportContest.holdSportGame();
- }
- }
3.线程具体业务逻辑类
(1)说明
本例线程执行的业务逻辑实现类均继承于同一个抽象类。因此,在Runnable接口的线程任务类中是基于抽象类编程。
(2)抽象类SportContest
全称:com.hub.example.p1.contest.SportContest
代码:
- public abstract class SportContest {
- //赛事任务
- private TaskDto taskDto;
- //开场仪式
- public abstract String announceStart();
- //举行比赛
- public abstract ResultDto playGame();
- //颁奖仪式
- public abstract String announceEnd(ResultDto resultDto);
- //举行体育赛事
- public String holdSportGame() {
- String result01 = announceStart();
- ResultDto result02 = playGame();
- String result03 = announceEnd(result02);
- return result03;
- }
- public TaskDto getTaskDto() {
- return taskDto;
- }
- public void setTaskDto(TaskDto taskDto) {
- this.taskDto = taskDto;
- }
- }
(3)实现类BadmintonContest
全称:com.hub.example.p1.contest.impl.BadmintonContest
代码:
- public class BadmintonContest extends SportContest {
- public BadmintonContest(TaskDto taskDto){
- this.setTaskDto(taskDto);
- }
- @Override
- public String announceStart() {
- TaskDto taskDto = this.getTaskDto();
- System.out.println("举行羽毛球比赛入场仪式:");
- System.out.println("羽毛球比赛入场仪式步骤一: "+taskDto.getEventName()+"队员入场.");
- System.out.println("羽毛球比赛入场仪式步骤二: 裁判员、教练员等各就各位.");
- return "羽毛球比赛进行中";
- }
- @Override
- public ResultDto playGame() {
- TaskDto taskDto = this.getTaskDto();
- System.out.println("举行羽毛球比赛: "+taskDto.getContent()+",选手们在奋力搏击.");
- return ResultDto.builder().teamName("中国羽毛球队").content("男单决赛冠军").build();
- }
- @Override
- public String announceEnd(ResultDto resultDto) {
- System.out.println("举行羽毛球比赛颁奖仪式: ");
- System.out.println("羽毛球比赛颁奖步骤一: 为"+resultDto.getTeamName()+resultDto.getContent()+"颁发金牌.");
- System.out.println("羽毛球比赛颁奖步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.");
- return "羽毛球比赛圆满结束";
- }
- }
(4)实现类DivingContest
全称:com.hub.example.p1.contest.impl.BadmintonContest
代码:
- public class DivingContest extends SportContest {
- public DivingContest(TaskDto taskDto) {
- this.setTaskDto(taskDto);
- }
- @Override
- public String announceStart() {
- TaskDto taskDto = this.getTaskDto();
- System.out.println("举行跳水比赛入场仪式:");
- System.out.println("跳水比赛入场仪式步骤一: "+taskDto.getEventName()+"队员入场.");
- System.out.println("跳水比赛入场仪式骤二: 裁判员、教练员等各就各位.");
- return "跳水比赛进行中";
- }
- @Override
- public ResultDto playGame() {
- TaskDto taskDto = this.getTaskDto();
- System.out.println("举行跳水比赛: " + taskDto.getContent() + ",姑娘们在冲刺记录.");
- return ResultDto.builder().teamName("中国跳水队").content("女子10米台跳板决赛冠军").build();
- }
- @Override
- public String announceEnd(ResultDto resultDto) {
- System.out.println("跳水比赛举行颁奖仪式: ");
- System.out.println("跳水比赛举行颁奖仪式步骤一: 为"+resultDto.getTeamName()+resultDto.getContent()+"颁发金牌.");
- System.out.println("跳水比赛举行颁奖仪式步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.");
- return "跳水比赛圆满结束";
- }
- }
4.把Runnable接口的线程任务类提交到线程池
(1)说明
Runnable接口的线程任务类需提交到线程池才能具体执行。
(2)代码
- @Component("sportWorker01")
- public class SportWorker01 {
- /**
- * 自动注入线程池
- * */
- @Autowired
- private ThreadPoolExecutor threadPoolExecutor;
-
- /**
- * 把线程任务提交到线程池
- */
- public void holdGame() {
- SportContest tableTennis = createBean("com.hub.example.p1.contest.impl.BadmintonContest",
- TaskDto.builder().eventName("羽毛球球比赛").content("男单决赛").build());
- SportContestExecutor executor01= new SportContestExecutor(tableTennis);
- SportContest swimming = createBean("com.hub.example.p1.contest.impl.DivingContest",
- TaskDto.builder().eventName("跳水比赛").content("女子10米台跳板决赛").build());
- SportContestExecutor executor02= new SportContestExecutor(swimming);
- threadPoolExecutor.execute(executor01);
- ThreadUtil.sleep(1000);
- threadPoolExecutor.execute(executor02);
- }
- /**
- * 使用Java反射方式创建对象
- */
- public SportContest createBean(String className, TaskDto params) {
- try {
- Class> clazz = Class.forName(className);
- Constructor> constructor = clazz.getConstructor(TaskDto.class);
- SportContest sportContest = (SportContest) constructor.newInstance(params);
- return sportContest;
- } catch (Exception e) {
- return null;
- }
- }
- }
5.测试示例
(1)说明
直接在SpringBoot的启动类的main函数中测试。
在执行完成SpringApplication.run(Example212Application.class)后,SpringBoot的环境已经创建完成。
(2)代码
- @SpringBootApplication
- public class Example212Application {
- public static void main(String[] args) {
- SpringApplication.run(Example212Application.class);
- SportWorker01 sportWorker01 = SpringUtil.getBean("sportWorker01");
- sportWorker01.holdGame();
- }
- }
(3)输出结果
- 【线程: pool-1-thread-1,在直播: 羽毛球球比赛】
- 举行羽毛球比赛入场仪式:
- 羽毛球比赛入场仪式步骤一: 羽毛球球比赛队员入场.
- 羽毛球比赛入场仪式步骤二: 裁判员、教练员等各就各位.
- 举行羽毛球比赛: 男单决赛,选手们在奋力搏击.
- 举行羽毛球比赛颁奖仪式:
- 羽毛球比赛颁奖步骤一: 为中国羽毛球队男单决赛冠军颁发金牌.
- 羽毛球比赛颁奖步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.
- 【线程: pool-1-thread-2,在直播: 跳水比赛】
- 举行跳水比赛入场仪式:
- 跳水比赛入场仪式步骤一: 跳水比赛队员入场.
- 跳水比赛入场仪式骤二: 裁判员、教练员等各就各位.
- 举行跳水比赛: 女子10米台跳板决赛,姑娘们在冲刺记录.
- 跳水比赛举行颁奖仪式:
- 跳水比赛举行颁奖仪式步骤一: 为中国跳水队女子10米台跳板决赛冠军颁发金牌.
- 跳水比赛举行颁奖仪式步骤二: 升中华人民共和国国旗,奏中华人民共和国国歌.
6.辅助实体类
(1)说明
在实体类中使用注解@Data等来自lombok-1.18.24.jar。
(2)TaskDto
- @Data
- @Builder
- @AllArgsConstructor
- @NoArgsConstructor
- public class TaskDto implements Serializable {
- //赛事名称
- private String eventName;
- //活动内容
- private String content;
- }
(3)ResultDto
- @Data
- @Builder
- @AllArgsConstructor
- @NoArgsConstructor
- public class ResultDto implements Serializable {
- //竞赛队伍
- private String teamName;
- //比赛成绩
- private String content;
- }
以上,感谢。
2023年9月13日