pom.xml配置导入如下:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

yml文件添加多线程核心配置

server:
  #端口号
  port: 8080
spring:
  task:
    pool:
      corePoolSize: 4
      maxPoolSize: 8
      keepAliveSeconds: 60
      queueCapacity: 20

corePoolSize不宜超过cpu核心数

创建线程池参数装载类:

@ConfigurationProperties(prefix = “spring.task.pool”)是让spring在创建bean时去加载配置文件中开头为spring.task.pool的内容,如果的配置文件位置不同的话可以引用别处。

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "spring.task.pool")
public class TaskThreadPoolConfig {
    private int corePoolSize;

    private int maxPoolSize;

    private int keepAliveSeconds;

    private int queueCapacity;

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public void setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    public void setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }

    public int getKeepAliveSeconds() {
        return keepAliveSeconds;
    }

    public void setKeepAliveSeconds(int keepAliveSeconds) {
        this.keepAliveSeconds = keepAliveSeconds;
    }

    public int getQueueCapacity() {
        return queueCapacity;
    }

    public void setQueueCapacity(int queueCapacity) {
        this.queueCapacity = queueCapacity;
    }
}

spring boot 启动类上加上注解:
@EnableConfigurationProperties({TaskThreadPoolConfig.class})
这个不能忘记,不然没法异步

@Configuration
@SpringBootApplication(scanBasePackages = "com",exclude = DataSourceAutoConfiguration.class)
@MapperScan(basePackages = "com.aistar.resources.mapper")
@EnableConfigurationProperties({TaskThreadPoolConfig.class})
public class LoginServiceApplication  {
    public static void main(String[] args) {
        SpringApplication.run(LoginServiceApplication.class, args);
    }
}

下面是一个简单demo使用方法:

测试类代码如下:

@SpringBootTest
class LoginServiceApplicationTests {

    @Autowired
    SysLoginUserService sysLoginUserService;
    @Autowired
    AsyncService asyncService;

    @Autowired
    SysParameterMapper sysParameterMapper;

    @Value("${config.jwt.secret}")
    private String secret;
    @Test
    void contextLoads() {
    }

    @Test
    public void test() throws ExecutionException, InterruptedException{
        long start = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();
        List<Future<String>> futures = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            Future<String> future = asyncService.doReturn(i);
            futures.add(future);
        }
        List<String> response = new ArrayList<>();
        for (Future future : futures) {
            String string = (String) future.get();
            response.add(string);
        }
        map.put("data", response);
        map.put("消耗时间", String.format("任务执行成功,耗时{%s}毫秒", System.currentTimeMillis() - start));
        System.out.println(map);
    }

}

创建service层:

public interface AsyncService {
    Future<String> doReturn(int i);
    
     void doReturnNores(int i);
}

实现类:

@Service
public class AsyncServiceImpl implements AsyncService {
    @Async("taskAsyncPool")
    public Future<String> doReturn(int i){
        try {
            // 这个方法需要调用500毫秒
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 消息汇总
        return new AsyncResult<>(String.format("这个是第{%s}个异步调用的证书", i));
    }
    
   @Async("taskAsyncPool")
    public void doReturnNores(int i){
        try {
            // 这个方法需要调用500毫秒
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

  • {data=[这个是第{0}个异步调用的证书, 这个是第{1}个异步调用的证书, 这个是第{2}个异步调用的证书,
    这个是第{3}个异步调用的证书, 这个是第{4}个异步调用的证书, 这个是第{5}个异步调用的证书, 这个是第{6}个异步调用的证书,
    这个是第{7}个异步调用的证书, 这个是第{8}个异步调用的证书, 这个是第{9}个异步调用的证书, 这个是第{10}个异步调用的证书,
    这个是第{11}个异步调用的证书, 这个是第{12}个异步调用的证书, 这个是第{13}个异步调用的证书,
    这个是第{14}个异步调用的证书, 这个是第{15}个异步调用的证书, 这个是第{16}个异步调用的证书,
    这个是第{17}个异步调用的证书, 这个是第{18}个异步调用的证书, 这个是第{19}个异步调用的证书,
    这个是第{20}个异步调用的证书, 这个是第{21}个异步调用的证书, 这个是第{22}个异步调用的证书,
    这个是第{23}个异步调用的证书, 这个是第{24}个异步调用的证书, 这个是第{25}个异步调用的证书,
    这个是第{26}个异步调用的证书, 这个是第{27}个异步调用的证书, 这个是第{28}个异步调用的证书,
    这个是第{29}个异步调用的证书, 这个是第{30}个异步调用的证书, 这个是第{31}个异步调用的证书,
    这个是第{32}个异步调用的证书, 这个是第{33}个异步调用的证书, 这个是第{34}个异步调用的证书,
    这个是第{35}个异步调用的证书, 这个是第{36}个异步调用的证书, 这个是第{37}个异步调用的证书,
    这个是第{38}个异步调用的证书, 这个是第{39}个异步调用的证书, 这个是第{40}个异步调用的证书,
    这个是第{41}个异步调用的证书, 这个是第{42}个异步调用的证书, 这个是第{43}个异步调用的证书,
    这个是第{44}个异步调用的证书, 这个是第{45}个异步调用的证书, 这个是第{46}个异步调用的证书,
    这个是第{47}个异步调用的证书, 这个是第{48}个异步调用的证书, 这个是第{49}个异步调用的证书,
    这个是第{50}个异步调用的证书, 这个是第{51}个异步调用的证书, 这个是第{52}个异步调用的证书,
    这个是第{53}个异步调用的证书, 这个是第{54}个异步调用的证书, 这个是第{55}个异步调用的证书,
    这个是第{56}个异步调用的证书, 这个是第{57}个异步调用的证书, 这个是第{58}个异步调用的证书,
    这个是第{59}个异步调用的证书, 这个是第{60}个异步调用的证书, 这个是第{61}个异步调用的证书,
    这个是第{62}个异步调用的证书, 这个是第{63}个异步调用的证书, 这个是第{64}个异步调用的证书,
    这个是第{65}个异步调用的证书, 这个是第{66}个异步调用的证书, 这个是第{67}个异步调用的证书,
    这个是第{68}个异步调用的证书, 这个是第{69}个异步调用的证书, 这个是第{70}个异步调用的证书,
    这个是第{71}个异步调用的证书, 这个是第{72}个异步调用的证书, 这个是第{73}个异步调用的证书,
    这个是第{74}个异步调用的证书, 这个是第{75}个异步调用的证书, 这个是第{76}个异步调用的证书,
    这个是第{77}个异步调用的证书, 这个是第{78}个异步调用的证书, 这个是第{79}个异步调用的证书,
    这个是第{80}个异步调用的证书, 这个是第{81}个异步调用的证书, 这个是第{82}个异步调用的证书,
    这个是第{83}个异步调用的证书, 这个是第{84}个异步调用的证书, 这个是第{85}个异步调用的证书,
    这个是第{86}个异步调用的证书, 这个是第{87}个异步调用的证书, 这个是第{88}个异步调用的证书,
    这个是第{89}个异步调用的证书, 这个是第{90}个异步调用的证书, 这个是第{91}个异步调用的证书,
    这个是第{92}个异步调用的证书, 这个是第{93}个异步调用的证书, 这个是第{94}个异步调用的证书,
    这个是第{95}个异步调用的证书, 这个是第{96}个异步调用的证书, 这个是第{97}个异步调用的证书,
    这个是第{98}个异步调用的证书, 这个是第{99}个异步调用的证书], 消耗时间=任务执行成功,耗时{6014}毫秒}

每个线程500ms,100次执行结果下耗时6014,还算是ok的节约不少时间,我觉得还有优化空间。
如果是不需要返回结果的话可以执行下方这段test2,比如短信发送这类业务。
一般如果是并行查询数据的话应该都是要返回数据的,需要返回数据需要用Future<> 包裹,取得时候也是要先get出来,否则是没法阻塞的。

@Test
    public void test2() throws ExecutionException, InterruptedException{
        long start = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();
        List<Future<String>> futures = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            asyncService.doReturnNores(i);
        }
    }

以上就是全部教程了,学习犹如逆水行舟,不进则退。