线程池实战篇

文章介绍了线程池在执行异步和并发任务时的重要性,包括降低资源消耗、提高响应速度、管控线程并发数量等优势。通过示例展示了如何在Spring中配置和使用ThreadPoolTaskExecutor,以及解决配置错误问题。
摘要由CSDN通过智能技术生成

        线程池使用场景

在执行异步任务或者并发任务的时候,我们往往用new Thread()方法来创建新的线程,这样弊端较多,如频繁的创建销毁线程占用大量系统资源,线程上线不可控,资源耗尽的风险,这时候可以引入线程池就比较合理,使用线程池的优势有哪些:

        使用线程池优点:

1. 降低系统系统资源消耗,重用已有的线程,减小创建销毁线程的资源消耗。

2. 提高系统响应速度,任务达到就有线程执行,无需等待新线程的创建。

3. 方便线程并发数量的管控,线程若是无限制的创建,不仅会额外消耗大量系统资源,更是占用过多资源而阻塞系统,从而降低系统的稳定性。线程池能有效管控线程,统一分配、调优,提供资源使用率;

4. 线程池它有自己独特的功能,如定时,可控线程数量,使用简单方便。
 

1.0 线程池的实现方式

        1.1 定义一个线程池,并 @EnableAsync 开启异步,在需要异步执行的方法上增加 @Async

        1.2 实现 AsyncConfigurer 接口,在需要异步支持的方法上使用 @Async

下面逐一实现这两种方式

task:
  pool:
    corePoolSize: 5
    maxPoolSize: 20
    keepAliveSeconds: 300
    queueCapacity: 50
package com.fei.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;



@Data
@EnableAsync
@Configuration
@ConfigurationProperties(prefix = "task")
public class ExecutorConfig {

    @Value("${task.pool.corePoolSize}")
    private int corePoolSize;

    @Value("${task.pool.maxPoolSize}")
    private int maxPoolSize;

    @Value("${task.pool.queueCapacity}")
    private int queueCapacity;
    @Value("${task.pool.keepAliveSeconds}")
    private int keepAliveSeconds;

    private static String NAME_PREFIX = "thread-call-runner-%d-";

    @Bean(name = "asyncServiceExecutor")
    public ThreadPoolTaskExecutor asyncServiceExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        threadPoolTaskExecutor.setThreadNamePrefix(NAME_PREFIX);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //加载
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

        进行测试

package com.fei.controller;

import com.fei.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
public class ThreadController {

    @Autowired
    private AsyncService asyncService;

    @Autowired
    private ThreadPoolTaskExecutor threadPool;

    @RequestMapping("test")
    public void testAsync() throws InterruptedException {
        System.out.println("testAsync 执行开始");
        TimeUnit.SECONDS.sleep(2);
        asyncService.executeAsync();
        asyncService.executeAsync();
        System.out.println("testAsync 执行完毕");
    }
    @RequestMapping("testThreadPool")
    public void testThreadPool() throws InterruptedException {
        System.out.println("testThreadPool start");
        TimeUnit.SECONDS.sleep(2);
        threadPool.execute(() -> System.out.println("threadPool testThreadPool"));
        System.out.println("testThreadPool end");
    }
}
package com.fei.service.impl;

import com.fei.service.AsyncService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncServiceImpl implements AsyncService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);

    @Async("asyncServiceExecutor")
    @Override
    public void executeAsync() {
        logger.info("------开始执行异步任务------");
        System.out.println("start executeAsync");
        System.out.println("当前运行的线程名称:" + Thread.currentThread().getName());
        for(int i=0 ;i<5000;i++){
            System.out.println(Thread.currentThread().getName()+"----->"+i);
        }
        logger.info("end executeAsync");
        System.out.println("------异步任务执行结束------");
    }
}

测试

第二种方式给第一种方式差不多,主要实现AsyncConfigurer之后和第一种方法相同。

ThreadPoolExecutor 和ThreadPoolTaskExecutor的区别,后者对前者进行封装,ThreadPoolExecutor  属于jdk自带的,ThreadPoolTaskExecutor 属于spring自带的。

遇到的问题

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'executorConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'task.poll.corePoolSize' in value "${task.poll.corePoolSize}"
	

发现是@Value注解中路径写错了pool写成poll了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周小代

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值