亲宝软件园·资讯

展开

Springboot 配置线程池

繁华尽头满是殇 人气:10

前言

众所周知,创建显示线程和直接使用未配置的线程池创建线程,都会被阿里的大佬给diss,所以我们要规范的创建线程。

至于 @Async 异步任务的用处是不想等待方法执行完就返回结果,提高软件前台响应速度,一个程序中会用到很多异步方法,所以需要使用线程池管理,防止影响性能。

一、创建一个Springboot Web项目

需要一个Springboot项目

二、新建ThreadPoolConfig

也可以自己new一个ThreadPoolExecutor自定义参数

参数说明:

阻塞队列的实现类:

 处理策略Handler:

线程池的关闭:

 shutdown() : 不会立刻终止线程,等所有缓存队列中的任务都执行完毕后才会终止。
shutdownNow() : 立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

package com.xuyijie.threadpooldemo.config;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.*;

/**
 * @author 徐一杰
 * @date 2022/9/20 13:05
 * @description 配置线程池
 */
@SpringBootConfiguration
@EnableAsync
public class ThreadPoolConfig {

    @Bean
    public ExecutorService getThreadPool(){
        ExecutorService threadPool = new ThreadPoolExecutor(2,5,
                1L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        return threadPool;
//        return Executors.newCachedThreadPool();
    }

    /**
     * 下面的配置是配置Springboot的@Async注解所用的线程池
     */
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //获取到cpu内核数
        int i = Runtime.getRuntime().availableProcessors();
        // 设置线程池核心容量
        executor.setCorePoolSize(i);
        // 设置线程池最大容量
        executor.setMaxPoolSize(i * 2);
        // 设置任务队列长度
        executor.setQueueCapacity(200);
        // 设置线程超时时间
        executor.setKeepAliveSeconds(60);
        // 设置线程名称前缀
        executor.setThreadNamePrefix("xyjAsyncPool-");
        // 设置任务丢弃后的处理策略,当poolSize已达到maxPoolSize,如何处理新任务(是拒绝还是交由其它线程处理),CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

}

使用此线程池时直接注入ExecutorService,然后:

executorService.execute(() -> {
 try {
String message = redisUtil.listRightPop(“queue:queueData”, 5, TimeUnit.SECONDS);
System.out.println(“接收到了消息message” + message);
} catch (Exception ex) {
date.set(simpleDateFormat.format(new Date()));
System.out.println(“队列阻塞超时-” + date + ex.getMessage());
} finally {
 date.set(simpleDateFormat.format(new Date()));
System.out.println(“线程销毁-” + date);
executorService.shutdown();
}
 });

三、新建controller测试

package com.xuyijie.threadpooldemo.controller;

import com.xuyijie.threadpooldemo.async.AsyncMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutorService;

/**
 * @author 徐一杰
 * @date 2022/9/20 10:30
 * @description
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private ExecutorService executorService;
    @Autowired
    private AsyncMethod asyncMethod;
    
    @GetMapping("/helloThread")
    public void helloThread(){
        executorService.execute(() -> {
            for (int i = 0;i < 100;i++){
                System.out.println("111");
            }
        });
        executorService.execute(() -> {
            for (int i = 0;i < 100;i++){
                System.out.println("222");
            }
        });
    }
	
	@GetMapping("/helloAsync")
    public String helloAsync(){
    	// 这个方法是异步的
        asyncMethod.print();
        System.out.println("print方法还在循环,但我已经可以执行了");
        return "print方法还在循环,但我已经可以执行了";
    }

}

AsyncMethod.java

package com.xuyijie.threadpooldemo.async;

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

/**
 * @author 徐一杰
 * @date 2022/9/20 15:10
 * @description 异步方法
 */
@Component
public class AsyncMethod {

	/**
     * 异步方法,如果@Async加在类的上面,则整个类中的方法都是异步的
     */
    @Async
    public void print(){
        for (int i = 0;i < 100;i++){
            System.out.println(i);
        }
    }
}

四、演示结果

首先演示 helloThread 这个接口,创建了2个线程,发现他们并发执行,成功

再演示 helloAsync 这个接口,发现 System.out.println("print方法还在循环,但我已经可以执行了");这行代码无需等待上面AsyncMethod中的 print 方法执行完毕,就可以开始执行,说明 print 方法是异步的,而且我输出的日志注意看,[xyjAsyncPool - ],我设置的线程池前缀,已经生效了,成功

加载全部内容

相关教程
猜你喜欢
用户评论