Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用

发布时间:2022-02-25 15:45:53 作者:iii
来源:亿速云 阅读:413

这篇文章主要介绍了Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用文章都会有所收获,下面我们一起来看看吧。

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。

一、ThreadPoolTaskExecutor

本文采用 Executors 的工厂方法进行配置。

1、将线程池用到的参数定义到配置文件中

在项目的 resources 目录下创建 executor.properties 文件,并添加如下配置:

# 异步线程配置
# 核心线程数
async.executor.thread.core_pool_size=5
# 最大线程数
async.executor.thread.max_pool_size=8
# 任务队列大小
async.executor.thread.queue_capacity=2
# 线程池中线程的名称前缀
async.executor.thread.name.prefix=async-service-
# 缓冲队列中线程的空闲时间
async.executor.thread.keep_alive_seconds=100

2、Executors 的工厂配置

2.1、配置详情
@Configuration
// @PropertySource是找的target目录下classes目录下的文件,resources目录下的文件编译后会生成在classes目录
@PropertySource(value = {"classpath:executor.properties"}, ignoreResourceNotFound=false, encoding="UTF-8")
@Slf4j
public class ExecutorConfig {
    @Value("${async.executor.thread.core_pool_size}")
    private int corePoolSize;
    @Value("${async.executor.thread.max_pool_size}")
    private int maxPoolSize;
    @Value("${async.executor.thread.queue_capacity}")
    private int queueCapacity;
    @Value("${async.executor.thread.name.prefix}")
    private String namePrefix;
    @Value("${async.executor.thread.keep_alive_seconds}")
    private int keepAliveSeconds;
    @Bean(name = "asyncTaskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        log.info("启动");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(corePoolSize);
        // 最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        // 任务队列大小
        executor.setQueueCapacity(queueCapacity);
        // 线程前缀名
        executor.setThreadNamePrefix(namePrefix);
        // 线程的空闲时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 线程初始化
        executor.initialize();
        return executor;
    }
}
2.2、注解说明
2.3、线程池配置说明
2.4、线程池配置个人理解

二、异步调用线程

通常 ThreadPoolTaskExecutor 是和 @Async 一起使用。在一个方法上添加 @Async 注解,表明是异步调用方法函数。

@Async 后面加上线程池的方法名或 bean 名称,表明异步线程会加载线程池的配置。

@Component
@Slf4j
public class ThreadTest {
    /**
     * 每10秒循环一次,一个线程共循环10次。
     */
    @Async("asyncTaskExecutor")
    public void ceshi3() {
        for (int i = 0; i <= 10; i  ) {
            log.info("ceshi3: "   i);
            try {
                Thread.sleep(2000 * 5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

备注:一定要在启动类上添加 @EnableAsync 注解,这样 @Async 注解才会生效。

三、多线程使用场景

1、定时任务 @Scheduled

// 在启动类上添加 @EnableScheduling 注解
@SpringBootApplication
@EnableScheduling
public class SpringBootStudyApplication {
   public static void main(String[] args) {
      SpringApplication.run(SpringBootStudyApplication.class, args);
   }
}
// @Component 注解将定时任务类纳入 spring bean 管理。
@Component
public class listennerTest3 {
    @Autowired
    private ThreadTest t;
    
    // 每1分钟执行一次ceshi3()方法
    @Scheduled(cron = "0 0/1 * * * ?")
    public void run() {
        t.ceshi3();
    }
}

ceshi3() 方法调用线程池配置,且异步执行。

@Component
@Slf4j
public class ThreadTest {
    /**
     * 每10秒循环一次,一个线程共循环10次。
     */
    @Async("asyncTaskExecutor")
    public void ceshi3() {
        for (int i = 0; i <= 10; i  ) {
            log.info("ceshi3: "   i);
            try {
                Thread.sleep(2000 * 5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2、程序一启动就异步执行多线程

通过继承 CommandLineRunner 类实现。

@Component
public class ListennerTest implements CommandLineRunner {
    @Autowired
    private ThreadTest t;
    @Override
    public void run(String... args) {
        for (int i = 1; i <= 10; i  ) {
            t.ceshi();
        }
    }
}
@Component
@Slf4j
public class ThreadTest {
    @Async("asyncTaskExecutor")
    public void ceshi() {
        log.info("ceshi");
    }
}

3、定义一个 http 接口

还可以通过接口的形式来异步调用多线程:

@RestController
@RequestMapping("thread")
public class ListennerTest2 {
    @Autowired
    private ThreadTest t;
    @GetMapping("ceshi2")
    public void run() {
        for (int i = 1; i < 10; i  ) {
            t.ceshi2();
        }
    }
}
@Component
@Slf4j
public class ThreadTest {
    @Async("asyncTaskExecutor")
    public void ceshi2() {
        for (int i = 0; i <= 3; i  ) {
            log.info("ceshi2");
        }
    }
}

4、测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class ThreadRunTest {
    @Autowired
    private ThreadTest t;
    @Test
    public void thread1() {
        for (int i = 1; i <= 10; i  ) {
            t.ceshi4();
        }
    }
}
@Component
@Slf4j
public class ThreadTest {
    @Async("asyncTaskExecutor")
    public void ceshi4() {
        log.info("ceshi4");
    }
}

关于“Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. springboot中使用自定义线程池ThreadPoolTaskExecutor
  2. Spring中@Async注解如何实现异步调用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring threadpooltaskexecutor

上一篇:Spring Cloud中怎么自定义外部化扩展机制

下一篇:Spring WebFlux反应式编程设计及工作原理是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》