SpringBoot线程池的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot线程池的使用相关的知识,希望对你有一定的参考价值。

第一步、配置线程池

package com.kyy.springboot.pool;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * Auth: zhouhongliang
 * Date:2019/8/1
 */
@Configuration
public class GlobalConfig 
    @Bean
    public ThreadPoolTaskExecutor defaultThreadPool()
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //核心线程数量
        threadPoolTaskExecutor.setCorePoolSize(2);
        //最大线程数量
        threadPoolTaskExecutor.setMaxPoolSize(5);
        //队列中最大任务数
        threadPoolTaskExecutor.setQueueCapacity(2);
        //线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("ThreadPool-");
        //当达到最大线程数时如何处理新任务
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //线程空闲后最大存活时间
        threadPoolTaskExecutor.setKeepAliveSeconds(60);
        //初始化线程池
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    

第二步、创建Service

package com.kyy.springboot.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * Auth: zhouhongliang
 * Date:2019/8/1
 */
@Service
public class BootService 
    @Resource(name = "defaultThreadPool")
    private ThreadPoolTaskExecutor poolTaskExecutor;

    @Async
    public void testPool() 
        System.out.println("线程名称:" + Thread.currentThread().getName());
    

    public void testNoPool() 
        System.out.println("线程名称:" + Thread.currentThread().getName());
    

    public int testPoolTaskExecutor(int n) throws InterruptedException, ExecutionException 
        CountDownLatch countDownLatch = new CountDownLatch(n);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int sum = 0;
        for (int i = 1; i <= n; i++) 
            final int index = i;
            final Future<Integer> future = poolTaskExecutor.submit(() -> 
                Thread.sleep(5000);
                System.out.println(simpleDateFormat.format(new Date())+" "+Thread.currentThread().getName() + " 执行 " + index);
                countDownLatch.countDown();
                return 1;
            );
        
        countDownLatch.await();
        return sum;
    

第三步:创建Controller

package com.kyy.springboot.controller;

import com.kyy.springboot.service.BootService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;

/**
 * Auth: zhouhongliang
 * Date:2019/8/1
 */
@RestController
public class PoolController 
    @Autowired
    private BootService bootService;
    @RequestMapping("/pool")
    public String pool()
        for (int i=0;i<100;i++)
            bootService.testPool();
        
        return "pool test";
    
    @RequestMapping("/poolTask/n")
    public String poolTask(@PathVariable int n)
        long startTime = System.currentTimeMillis();
        try 
            bootService.testPoolTaskExecutor(n);
         catch (InterruptedException e) 
            e.printStackTrace();
         catch (ExecutionException e) 
            e.printStackTrace();
        
        long endTime = System.currentTimeMillis();
        return "poolTask test "+(endTime-startTime)/1000+" 秒";
    

第四步:创建启动类

package com.kyy.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * 启动程序
 * @Auther:zhouhongliang
 * @Date:2019/7/30
 * @Description:
 */
@SpringBootApplication
@EnableAsync
public class SpringBootDemo 
    public static void main(String[] args) 
        SpringApplication.run(SpringBootDemo.class,args);
    

总结:线程池配置说明
1、属性字段说明

corePoolSize:线程池维护线程的最少数量

keepAliveSeconds:允许的空闲时间

maxPoolSize:线程池维护线程的最大数量

queueCapacity:缓存队列

rejectedExecutionHandler:对拒绝task的处理策略

2、 execute(Runable)方法执行过程
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。

如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

以上是关于SpringBoot线程池的使用的主要内容,如果未能解决你的问题,请参考以下文章

springboot线程池的使用和扩展

springboot+线程池使用

springboot+@async异步线程池的配置及应用

助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoo

SpringBoot-技术专区-实战方案-应用监控线程池

SpringBoot 多线程