java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Springboot 配置线程池

Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解

作者:繁华尽头满是殇

这篇文章主要介绍了Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

前言

众所周知,创建显示线程和直接使用未配置的线程池创建线程,都会被阿里的大佬给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 - ],我设置的线程池前缀,已经生效了,成功

到此这篇关于Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解的文章就介绍到这了,更多相关Springboot 配置线程池 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文