spring boot使用自定义配置的线程池执行Async异步任务

在前面的博客中,http://www.jb51.net/article/106718.htm 我们使用了spring boot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池!

一、增加配置属性类

package com.chhliu.springboot.async.configuration;
import org.springframework.boot.context.properties.ConfigurationProperties; 

@ConfigurationProperties(prefix = "spring.task.pool") // 该注解的locations已经被启用,现在只要是在环境中,都会优先加载
public class TaskThreadPoolConfig {
 private int corePoolSize; 

 private int maxPoolSize; 

 private int keepAliveSeconds; 

 private int queueCapacity; 

 …………省略getter,setter方法…………
}

二、创建线程池

package com.chhliu.springboot.async.pool;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;
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 com.chhliu.springboot.async.configuration.TaskThreadPoolConfig; 

@Configuration
@EnableAsync
public class TaskExecutePool { 

 @Autowired
 private TaskThreadPoolConfig config; 

 @Bean
 public Executor myTaskAsyncPool() {
  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  executor.setCorePoolSize(config.getCorePoolSize());
  executor.setMaxPoolSize(config.getMaxPoolSize());
  executor.setQueueCapacity(config.getQueueCapacity());
  executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
  executor.setThreadNamePrefix("MyExecutor-"); 

  // rejection-policy:当pool已经达到max size的时候,如何处理新任务
  // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
  executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  executor.initialize();
  return executor;
 }
}

三、在主类中开启配置支持

package com.chhliu.springboot.async;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableAsync; 

import com.chhliu.springboot.async.configuration.TaskThreadPoolConfig; 

@SpringBootApplication
@EnableAsync
@EnableConfigurationProperties({TaskThreadPoolConfig.class} ) // 开启配置属性支持
public class SpringbootAsyncApplication { 

 public static void main(String[] args) {
  SpringApplication.run(SpringbootAsyncApplication.class, args);
 }
}

四、测试类

package com.chhliu.springboot.async.pool; 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; 

@Component
public class AsyncTask {
 protected final Logger logger = LoggerFactory.getLogger(this.getClass()); 

 @Async("myTaskAsyncPool") //myTaskAsynPool即配置线程池的方法名,此处如果不写自定义线程池的方法名,会使用默认的线程池
 public void doTask1(int i) throws InterruptedException{
  logger.info("Task"+i+" started.");
 }
}

五、测试

package com.chhliu.springboot.async;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; 

import com.chhliu.springboot.async.pool.AsyncTask; 

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAsyncApplicationTests {
 protected final Logger logger = LoggerFactory.getLogger(this.getClass());
 @Autowired
 private AsyncTask asyncTask; 

 @Test
 public void AsyncTaskTest() throws InterruptedException, ExecutionException { 

  for (int i = 0; i < 100; i++) {
   asyncTask.doTask1(i);
  } 

  logger.info("All tasks finished.");
 }
}

测试结果如下:

2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-10] c.c.springboot.async.pool.AsyncTask  : Task60 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-25] c.c.springboot.async.pool.AsyncTask  : Task61 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-6] c.c.springboot.async.pool.AsyncTask  : Task62 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-23] c.c.springboot.async.pool.AsyncTask  : Task63 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-20] c.c.springboot.async.pool.AsyncTask  : Task64 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-19] c.c.springboot.async.pool.AsyncTask  : Task65 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-16] c.c.springboot.async.pool.AsyncTask  : Task66 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-15] c.c.springboot.async.pool.AsyncTask  : Task67 started.
2017-03-20 20:15:15.208 INFO 4068 --- [ MyExecutor-12] c.c.springboot.async.pool.AsyncTask  : Task68 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-1] c.c.springboot.async.pool.AsyncTask  : Task69 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-11] c.c.springboot.async.pool.AsyncTask  : Task81 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-8] c.c.springboot.async.pool.AsyncTask  : Task82 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-7] c.c.springboot.async.pool.AsyncTask  : Task83 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-4] c.c.springboot.async.pool.AsyncTask  : Task84 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-29] c.c.springboot.async.pool.AsyncTask  : Task85 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-21] c.c.springboot.async.pool.AsyncTask  : Task86 started.
2017-03-20 20:15:15.209 INFO 4068 --- [ MyExecutor-17] c.c.springboot.async.pool.AsyncTask  : Task88 started. 

测试结果ok!

六、配置默认的线程池

如果我们想使用默认的线程池,但是只是想修改默认线程池的配置,那怎么做了,此时我们需要实现AsyncConfigurer类,示例代码如下:

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import com.chhliu.cq.emailservice.threadconfiguration.TaskThreadPoolConfig;
import lombok.extern.slf4j.Slf4j; 

/**
 * 注意:该线程池被所有的异步任务共享,而不属于某一个异步任务
 * 描述:配置异步任务的线程池
 * @author chhliu
 * 创建时间:2017年5月22日 上午10:20:56
 * @version 1.2.0
 */
@Slf4j
@Configuration
public class AsyncTaskExecutePool implements AsyncConfigurer{ 

 @Autowired
 private TaskThreadPoolConfig config; // 配置属性类,见上面的代码 

 @Override
 public Executor getAsyncExecutor() {
  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  executor.setCorePoolSize(config.getCorePoolSize());
  executor.setMaxPoolSize(config.getMaxPoolSize());
  executor.setQueueCapacity(config.getQueueCapacity());
  executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
  executor.setThreadNamePrefix("taskExecutor-"); 

  // rejection-policy:当pool已经达到max size的时候,如何处理新任务
  // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
  executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  executor.initialize();
  return executor;
 } 

 @Override
 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {// 异步任务中异常处理
  return new AsyncUncaughtExceptionHandler() { 

   @Override
   public void handleUncaughtException(Throwable arg0, Method arg1, Object... arg2) {
    log.error("=========================="+arg0.getMessage()+"=======================", arg0);
    log.error("exception method:"+arg1.getName());
   }
  };
 }
} 

使用的时候,只需在方法上加上@Async即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • 详解Spring-Boot中如何使用多线程处理任务
  • Spring boot多线程配置方法
(0)

相关推荐

  • 详解Spring-Boot中如何使用多线程处理任务

    看到这个标题,相信不少人会感到疑惑,回忆你们自己的场景会发现,在Spring的项目中很少有使用多线程处理任务的,没错,大多数时候我们都是使用Spring MVC开发的web项目,默认的Controller,Service,Dao组件的作用域都是单实例,无状态,然后被并发多线程调用,那么如果我想使用多线程处理任务,该如何做呢? 比如如下场景: 使用spring-boot开发一个监控的项目,每个被监控的业务(可能是一个数据库表或者是一个pid进程)都会单独运行在一个线程中,有自己配置的参数,总结起来

  • Spring boot多线程配置方法

    本文实例为大家分享了Spring boot多线程配置的具体代码,供大家参考,具体内容如下 1.配置线程配置类 package test; import java.util.concurrent.Executor; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.ComponentScan; import o

  • spring boot使用自定义配置的线程池执行Async异步任务

    在前面的博客中,http://www.jb51.net/article/106718.htm 我们使用了spring boot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池! 一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.springframework.boot.context.properties.ConfigurationP

  • spring boot使用自定义配置的线程池执行Async异步任务

    目录 一.增加配置属性类 二.创建线程池 三.在主类中开启配置支持 四.测试类 五.测试 六.配置默认的线程池 在前面的博客中,//www.jb51.net/article/106718.htm 我们使用了spring boot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池! 一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.spr

  • spring boot使用自定义的线程池执行Async任务

    在前面的博客中,//www.jb51.net/article/134866.htm 我们使用了spring boot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池! 一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.springframework.boot.context.properties.ConfigurationProper

  • 初识Spring Boot框架之Spring Boot的自动配置

    在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单的Spring Boot 自动配置的案例,看看这一切到底是怎么发生的. 假设我的需求是这样的:当我的项目中存在某个类的时候,系统自动为我配置该类的Bean,同时,我这个Bean的属性还可以在application.properties中进行配置,OK,就这样一个需求,我们来看看怎么实现. 1.新建s

  • Spring Boot使用和配置Druid

    1.引入依赖包 <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.27</version> </dependency> 2.配置application.properties spring.datasource.type=com.alibaba.dru

  • spring boot日志管理配置

    spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J,Log4J2和Logback.每种Logger都可以通过配置使用控制台或者文件输出日志内容. 控制台输出 在Spring Boot中默认配置了ERROR.WARN和INFO级别的日志输出到控制台. 我们可以通过两种方式切换至DEBUG级别: a.在运行命令后加入--debug标志,如:$ Java -jar myapp.jar --d

  • Spring Boot中自定义注解结合AOP实现主备库切换问题

    摘要:本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的压力,在本篇文章中主要记录在Spring Boot中通过自定义注解结合AOP实现直接连接备库查询. 一.通过AOP 自定义注解实现主库到备库的切换 1.1 自定义注解 自定义注解如下代码所示 import java.lang.annotation.ElementType; import java.la

  • Spring Boot读取自定义配置文件

    @Value 首先,会想到使用@Value注解,该注解只能去解析yaml文件中的简单类型,并绑定到对象属性中去. felord:   phone: 182******32   def:     name: 码农小胖哥     blog: felord.cn     we-chat: MSW_623   dev:     name: 码农小胖哥     blog: felord.cn     we-chat: MSW_623   type: JUEJIN 对于上面的yaml配置,如果我们使用@Va

  • spring boot下mybatis配置双数据源的实例

    目录 单一数据源配置 多个数据源配置 多数据源配置文件 多数据源配置类 最近项目上遇到需要双数据源的来实现需求,并且需要基于spring boot,mybatis的方式来实现,在此做简单记录. 单一数据源配置 单一数据源配置的话并没有什么特别的,在spring boot框架下,只需要在配置文件内添加对应的配置项即可,spring boot会自动初始化需要用到的bean. 配置信息如下.这里使用的是德鲁伊的数据源配置方式 #datasource配置 spring.datasource.type=c

  • spring boot的maven配置依赖详解

    本文介绍了spring boot的maven配置依赖详解,分享给大家,具体如下: 我们通过引用spring-boot-starter-parent,添加spring-boot-starter-web 可以实现web项目的功能,当然不使用spring-boot-start-web,通过自己添加的依赖包也可以实现,但是需要一个个添加,费时费力,而且可能产生版本依赖冲突.我们来看下springboot的依赖配置: 利用pom的继承,一处声明,处处使用.在最顶级的spring-boot-dependen

随机推荐