某些情况下,我们需要在项目中对多种任务分配不同的线程池进行执行。从而通过监控不同的线程池来控制不同的任务。为了达到这个目的,需要在项目中配置多线程池。
配置类
package com.demo.config;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Executor;
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
@Bean
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
// ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(5);
//配置最大线程数
executor.setMaxPoolSize(5);
//配置队列大小
executor.setQueueCapacity(99999);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("async-service-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
package com.demo.config;
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;
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 <T> Future<T> submit(Callable<T> 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 <T> ListenableFuture<T> submitListenable(Callable<T> task) {
showThreadPoolInfo("2. do submitListenable");
return super.submitListenable(task);
}
}
工具类
package com.demo.entity;
import lombok.Data;
@Data
public class ResultVo {
private int code;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
private String msg;
private Object data;
private long ID;
public static ResultVo success(String mes) {
ResultVo resultVo = new ResultVo();
resultVo.setCode(200);
resultVo.setMsg(mes);
return resultVo;
}
public static ResultVo successID(String mes,long ID) {
ResultVo resultVo = new ResultVo();
resultVo.setCode(200);
resultVo.setMsg(mes);
resultVo.setID(ID);
return resultVo;
}
public static ResultVo success(Object obj) {
ResultVo resultVo = new ResultVo();
resultVo.setCode(200);
resultVo.setData(obj);
resultVo.setMsg("ok");
return resultVo;
}
public static ResultVo failure(String mes) {
ResultVo resultVo = new ResultVo();
resultVo.setCode(400);
resultVo.setMsg(mes);
return resultVo;
}
public static ResultVo failure(Integer code) {
ResultVo resultVo = new ResultVo();
resultVo.setCode(code);
return resultVo;
}
public static ResultVo success(Boolean mes) {
ResultVo resultVo = new ResultVo();
if(mes){
resultVo.setCode(200);
resultVo.setMsg("ok");
}else{
resultVo.setCode(400);
resultVo.setMsg("find");
}
return resultVo;
}
}
请求借口
package com.demo.controller;
import com.demo.entity.ResultVo;
import com.demo.service.AsyncService;
import lombok.SneakyThrows;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile;
import java.util.concurrent.Future;
@RestController
public class Hello {
private static final Logger logger = LoggerFactory.getLogger(Hello.class);
@Autowired
private AsyncService asyncService;
/**
* 不带返回值
* @param multipartFile
*/
@RequestMapping("/asdasd")
public void submit(@Param("multipartFile") MultipartFile multipartFile){
logger.info("start submit");
asyncService.executeAsync(multipartFile);
logger.info("end submit");
}
/**
* 带返回值
*/
@SneakyThrows
@RequestMapping("/Filesasd")
public ResultVo heartBeat(@Param("multipartFile") MultipartFile multipartFile) {
logger.info("start submit");
ResultVo res = asyncService.insertTaskLog(multipartFile);
logger.info("end submit");
return res;
}
}
service
package com.demo.service;
import com.demo.entity.ResultVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.concurrent.Future;
public interface AsyncService {
/**
* 不带返回值
*/
void executeAsync(MultipartFile multipartFile);
/**
* 带返回值
* @return
*/
ResultVo insertTaskLog(MultipartFile multipartFile);
}
impl
package com.demo.service.impl;
import cn.hutool.log.LogFactory;
import com.demo.entity.ResultVo;
import com.demo.service.AsyncService;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
@Async("asyncServiceExecutor")
@SneakyThrows
public void executeAsync(MultipartFile multipartFile) {
//进行代码操作
logger.info("start executeAsync");
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
logger.info("end executeAsync");
}
@SneakyThrows
@Override
public ResultVo insertTaskLog(MultipartFile multipartFile) {
logger.info("start executeAsync");
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
logger.info("end executeAsync");
ResultVo resultVo = new ResultVo();
return new AsyncResult<ResultVo>(resultVo).get();
}
}