springboot自定义线程池

利用springboot提供的线程池,实现参数可配置的线程池。

第一,application.yml中添加如下配置

#线程池参数按需设置,不设置的时候给默认值
threadpool:
    #核心线程数(默认10)
    core_pool_size: 10
    #最大线程数(默认200)
    max_pool_size: 200
    #队列大小(默认1024)
    queue_capacity: 1024
    #空闲线程活跃时间(秒)(默认60)
    keep_alive_seconds: 60
    #默认线程名称(area-pool-)
    prefix_name: area-pool-

第二,增加配置类ThreadPoolAsyncConfig

如果想使用@Async注解来完成异步任务的话,需要在配置类上添加注解@EnableAsync,如果不使用注解完成异步的话,此注解可以省略。直接上代码吧:

package com.diwork.intelliv.workbench.analysis.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class ThreadPoolAsyncConfig {

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

    /**
     * 核心线程数
     */
    @Value("${threadpool.core_pool_size:10}")
    private int corePoolSize;
    /**
     * 最大线程数
     */
    @Value("${threadpool.max_pool_size:200}")
    private int maxPoolSize;
    /**
     * 队列大小
     */
    @Value("${threadpool.queue_capacity:1024}")
    private int queueCapacity;
    /**
     * 空闲线程活跃时间(秒)
     */
    @Value("${threadpool.keep_alive_seconds:60}")
    private int keepAliveSeconds;
    /**
     * 默认线程名称
     */
    @Value("${threadpool.prefix_name:area-pool-test}")
    private String threadNamePrefix;

    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor asyncServiceExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        logger.info("---------- 线程池开始加载 ----------");
        // 设置核心线程数
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        // 设置最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        // 配置队列大小
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        // 设置线程活跃时间(秒)
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        // 设置默认线程名称
        threadPoolTaskExecutor.setThreadNamePrefix(threadNamePrefix);
        // 设置拒绝策略
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 执行初始化
        threadPoolTaskExecutor.initialize();
        logger.info("corePoolSize [{}], maxPoolSize [{}],queueCapacity [{}], keepAliveSeconds [{}], threadNamePrefix [{}]",
            corePoolSize,
            maxPoolSize,
            queueCapacity,
            keepAliveSeconds,
            threadNamePrefix);
        logger.info("---------- 线程池加载完成 ----------");
        return threadPoolTaskExecutor;
    }
}

第三,线程的具体使用

1.注解使用线程池@Async

service类,注意注解的添加,这里需要注意的一点就是添加@Async想要实现异步的效果的话,必须保证调用者和异步方法不在同一个类中,否则,异步不生效。这一点很关键。

异步接口类AsyncService

package com.example.springboottest1.service;

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

@Service
public interface AsyncService {
    /**
     * 执行异步任务,注意这里的threadPoolTaskExecutor要跟配置类中的一致
     */
    @Async("threadPoolTaskExecutor")
    void executeAsync();
}

 异步实现类AsyncServiceImpl

package com.example.springboottest1.serviceimp;

import com.example.springboottest1.service.AsyncService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class AsyncServiceImpl implements AsyncService {

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

    @Override
    public void executeAsync() {
        try {
           logger.info("============================="+Thread.currentThread().getName());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.常规用法,直接在需要使用的service上面进行注入即可使用

@Resource(name = "threadPoolTaskExecutor")
private ThreadPoolTaskExecutor threadPool;

Future task = threadPool.submit(queryThread);

第四,就是线程的验证了,写个简单测试类

package com.example.springboottest1.controller;

import com.example.springboottest1.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ThreadController {

    @Autowired
    private AsyncService asyncService;

    @GetMapping("/sss")
    public String sss(){
        for (int i = 1; i <= 100; i++) {
            asyncService.executeAsync();
        }
        return "OK";
    }
}

第五,如果想要统计线程的使用情况,可以自定义一个类,并继承springboot提供的线程池类即可。只要把配置类中的

 ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();

改为

ThreadPoolTaskExecutor threadPoolTaskExecutor = new VisiableThreadPoolTaskExecutor();
package com.diwork.intelliv.workbench.analysis.exe.block;
/**
 *
 */

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.concurrent.ListenableFuture;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @className VisiableThreadPoolTaskExecutor
 * @description: TODO
 * @author Lancy
 * @date 2021/6/25 9:52
 * @version 1.0
 */
public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

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

    private void showThreadPoolInfo(String prefix) {
        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();

        if (null == threadPoolExecutor) {
            return;
        }

        logger.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
                this.getThreadNamePrefix(),
                prefix,
                threadPoolExecutor.getTaskCount(),
                threadPoolExecutor.getCompletedTaskCount(),
                threadPoolExecutor.getActiveCount(),
                threadPoolExecutor.getQueue().size());
    }

    @Override
    public void execute(Runnable task) {
        showThreadPoolInfo("1. do execute");
        super.execute(task);
    }

    @Override
    public void execute(Runnable task, long startTimeout) {
        showThreadPoolInfo("2. do execute");
        super.execute(task, startTimeout);
    }

    @Override
    public Future submit(Runnable task) {
        showThreadPoolInfo("1. do submit");
        return super.submit(task);
    }

    @Override
    public  Future submit(Callable task) {
        showThreadPoolInfo("2. do submit");
        return super.submit(task);
    }

    @Override
    public ListenableFuture submitListenable(Runnable task) {
        showThreadPoolInfo("1. do submitListenable");
        return super.submitListenable(task);
    }

    @Override
    public  ListenableFuture submitListenable(Callable task) {
        showThreadPoolInfo("2. do submitListenable");
        return super.submitListenable(task);
    }
}

至此完成线程的工作,可以去使用了!

你可能感兴趣的:(springboot,spring,springboot可配线程池,线程池注解Async的使用)