SpringBoot使用多线程

一、概述

1、为什么使用多线程

在我们开发系统过程中,经常会处理一些好费时间的任务(如:向数据库中插入上百万数据,将会导致系统等待),这个时候就会自然想到使用多线程。

2、为什么使用Spring来实现多线程

使用Spring比使用JDK原生的并发API更简单。(@Async就能解决)。
一般的开发环境都会集成Spring框架,Bean也都交给Spring来管理,因此,Spring实现多线程更简单。

3、为什么需要使用异步

传统的调用方式:调用一个服务,需要等待服务调用完成后,才能执行后面的代码,因此,需要等待时间。
使用异步的方式:调用一个服务的同时,继续执行后面的代码,几乎是不需要多少的等待时间。

4、线程池ThreadPoolExecutor执行规则如下

在这里插入图片描述

二、SpringBoot使用多线程

1、如何使用

在 SpringBoot 中对其进行了简化处理,只需要配置一个类型为 java.util.concurrent.TaskExecutor
或其子类的 bean,并在配置类或直接在程序入口类上声明注解 @EnableAsync。
调用也简单,在由Spring管理的对象的方法上标注注解 @Async,显式调用即可生效。 一般使用 Spring 提供的
ThreadPoolTaskExecutor 类。

2、新增一个配置类,默认情况下使用 SimpleAsyncTaskExecutor

@Configuration
@EnableAsync //启用异步任务
public class ThreadConfig {
    @Bean
    public ThreadPoolTaskExecutor executor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      	//配置核心线程数
        executor.setCorePoolSize(15);
      	//配置最大线程数
        executor.setMaxPoolSize(30);
      	//配置队列大小
        executor.setQueueCapacity(1000);
      	//线程的名称前缀
        executor.setThreadNamePrefix("Executor-");
      	//线程活跃时间(秒)
        //executor.setKeepAliveSeconds(60);
      	//等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
      	//设置拒绝策略
        //executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
      	//执行初始化
        executor.initialize();
        return executor;
    }
}


3、使用线程池

//-----------------------接口类--------------------------
public interface UserService{
  	/**
  	 * 执行异步任务
  	 */
  	void writeText();
}
//-----------------------接口实现类----------------------
@Service
public class UserServiceImpl implement UserService{
  	private static Logger logger = LogManager.getLogger(AsyncServiceImpl.class.getName());
 
    @Async("asyncServiceExecutor")
  	@Over
    public void writeTxt(String fileName){
        logger.info("线程-" + Thread.currentThread().getId() + "在执行写入");
        try {
            File file = new File(fileName);
            List<String> lines = FileUtils.readLines(file);
            File copyFile = new File(fileName + "_copy.txt");
            lines.stream().forEach(string->{
                try {
                    FileUtils.writeStringToFile(copyFile,string,"utf8",true);
                    FileUtils.writeStringToFile(copyFile,"\r\n","utf8",true);
                } catch (IOException e) {
                    logger.info(e.getMessage());
                }
            });
        }catch (Exception e) {
            logger.info(e.getMessage());
        }
    }
}
//-----------------------测试----------------------------
@RunWith(SpringRunner.class)
@SpringBootTest
public class BootApplicationTests {
	@Autowired
	private AsyncService asyncService;
 
    @Test
    public void write() {
        File file = new File("F://ac_code_1//test.txt");
        try {
            FileUtils.writeStringToFile(file, "ceshi", "utf8");
            FileUtils.writeStringToFile(file, "\r\n", "utf8");
            FileUtils.writeStringToFile(file, "ceshi2", "utf8");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


三、SpringBoot使用多线程批量插入数据

1、新建配置类

@Configuration
public class ThreadConfig {
    @Bean
    public ThreadPoolTaskExecutor executor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(15);
        //配置最大线程数
        executor.setMaxPoolSize(30);
        //配置队列大小
        executor.setQueueCapacity(1000);
        //线程的名称前缀
        executor.setThreadNamePrefix("Executor-");
        //等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //执行初始化
        executor.initialize();
        return executor;
    }
}

2、service接口类

public interface ExchangeCouponInfoService extends IService<ExchangeCodeInfo> {
    /**
     * 批量新增兑换码
     * @param info
     * @return
     */
    boolean addBatchExchangeCode(List<ExchangeCodeInfo> info);
}


3、接口实现类

@Service
public class ExchangeCodeInfoServiceImpl  extends ServiceImpl<ExchangeCodeInfoMapper, ExchangeCodeInfo> implements ExchangeCouponInfoService{
    @Override
    public boolean addBatchExchangeCode(List<ExchangeCodeInfo> info) {
        return saveBatch(info);
    }
}


4、controller类

@RestController
@RequestMapping("/exchangecoupon")
public class ExchangeCouponController {
    @Autowired
    private ExchangeCouponInfoService exchangeCouponInfoService;
  
  	@Autowired
    private ThreadPoolTaskExecutor executor;

    @PostMapping("/saveExchangeCoupon")
    @BizDigestLog(bizType = "兑换券新增")
    public Results saveExchangeCoupon(@RequestBody ExchangeCouponModelAddReqDto model){
        log.info("兑换券新增入口 -> [{}]",model);
      	//线程异步导入数据库,会异步开始执行新增方法,同时原线程不会等待,继续执行。实现了异步操作。
      	executor.execute(() -> exchangeCouponInfoService.addBatchExchangeCode(model));
        Results results = Results.success(response);
        log.info("兑换券新增出口 -> [{}]",JSON.toJSONString(response));
        return results;
    }
}


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计是高等教育阶段学生在完成学业前所进行的一项重要学术任务,旨在检验学生通过学习所获得的知识、技能以及对特定领域的深刻理解能力。这项任务通常要求学生运用所学专业知识,通过独立研究和创新,完成一个实际问题的解决方案或者开展一项有价值的项目。 首先,毕业设计的选择通常由学生根据个人兴趣、专业方向以及实际需求来确定。学生需要在导师的指导下明确研究目标、问题陈述,确立研究的范围和深度。毕业设计可以包括文献综述、需求分析、方案设计、实施与测试等多个阶段,以确保整个过程的科学性和系统性。 其次,毕业设计的完成通常需要学生具备一定的独立思考和解决问题的能力。在研究过程中,学生可能需要采用各种研究方法,如实验、调查、案例分析等,以获取必要的数据和信息。通过这些活动,学生能够培养扎实的专业技能,提升解决实际问题的实际能力。 第三,毕业设计的撰写是整个过程的重要组成部分。学生需要将研究过程、方法、结果以及结论等详细记录在毕业论文中,以展示其研究的全貌和成果。同时,撰写毕业设计还有助于提高学生的学术写作水平,培养清晰、逻辑的表达能力。 最后,毕业设计的评价通常由导师和相关专业人士进行。评价标准包括研究的创新性、实用性、方法的科学性以及论文的质量等方面。学生在毕业设计中获得的成绩也将直接影响其最终的学业成绩和学位授予。 总的来说,毕业设计是高等教育中的一项重要环节,通过此过程,学生不仅能够巩固所学知识,还能培养独立思考和解决问题的能力,为将来的职业发展奠定坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值