文档章节

spring-boot 方法异步调用,自定义线程池配置使用

weiliu007
 weiliu007
发布于 2017/04/07 09:10
字数 824
阅读 682
收藏 1

1、在主类中添加@EnableAsync注解:

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class MySpringBootApplication {
	private static Logger logger = LoggerFactory.getLogger(MySpringBootApplication.class);
	
	public static void main(String[] args) {
		SpringApplication.run(MySpringBootApplication.class, args);
		logger.info("My Spring Boot Application Started");
	}

	

2、创建一个AsyncTask类,在里面添加两个用@Async注解的task:

@Component
public class AsyncTask {
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Async
	public Future<String> doTask1() throws InterruptedException{
		logger.info("Task1 started.");
		long start = System.currentTimeMillis();
        Thread.sleep(5000);
        long end = System.currentTimeMillis();
        
        logger.info("Task1 finished, time elapsed: {} ms.", end-start);
        
        return new AsyncResult<>("Task1 accomplished!");
	}
	
	@Async
	public Future<String> doTask2() throws InterruptedException{
		logger.info("Task2 started.");
		long start = System.currentTimeMillis();
        Thread.sleep(3000);
        long end = System.currentTimeMillis();
        
        logger.info("Task2 finished, time elapsed: {} ms.", end-start);
        
        return new AsyncResult<>("Task2 accomplished!");
	}
}

3、万事俱备,开始测试:


public class TaskTests extends BasicUtClass{
	@Autowired
	private AsyncTask asyncTask;
	
	
	@Test
	public void AsyncTaskTest() throws InterruptedException, ExecutionException {
		Future<String> task1 = asyncTask.doTask1();
		Future<String> task2 = asyncTask.doTask2();
		
		while(true) {
			if(task1.isDone() && task2.isDone()) {
				logger.info("Task1 result: {}", task1.get());
				logger.info("Task2 result: {}", task2.get());
				break;
			}
			Thread.sleep(1000);
		}
		
		logger.info("All tasks finished.");
	}
}

测试结果:

2016-12-13 11:12:24,850:INFO main (AsyncExecutionAspectSupport.java:245) - No TaskExecutor bean found for async processing
2016-12-13 11:12:24,864:INFO SimpleAsyncTaskExecutor-1 (AsyncTask.java:22) - Task1 started.
2016-12-13 11:12:24,865:INFO SimpleAsyncTaskExecutor-2 (AsyncTask.java:34) - Task2 started.
2016-12-13 11:12:27,869:INFO SimpleAsyncTaskExecutor-2 (AsyncTask.java:39) - Task2 finished, time elapsed: 3001 ms.
2016-12-13 11:12:29,866:INFO SimpleAsyncTaskExecutor-1 (AsyncTask.java:27) - Task1 finished, time elapsed: 5001 ms.
2016-12-13 11:12:30,853:INFO main (TaskTests.java:23) - Task1 result: Task1 accomplished!
2016-12-13 11:12:30,853:INFO main (TaskTests.java:24) - Task2 result: Task2 accomplished!
2016-12-13 11:12:30,854:INFO main (TaskTests.java:30) - All tasks finished.

可以看到,没有自定义的Executor,所以使用缺省的TaskExecutor 。

 

前面是最简单的使用方法。如果想使用自定义的Executor,可以按照如下几步来:

1、新建一个Executor配置类,顺便把@EnableAsync注解搬到这里来:

@Configuration
@EnableAsync
public class ExecutorConfig {

	/** Set the ThreadPoolExecutor's core pool size. */
	private int corePoolSize = 10;
	/** Set the ThreadPoolExecutor's maximum pool size. */
	private int maxPoolSize = 200;
	/** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */
	private int queueCapacity = 10;

	@Bean
	public Executor mySimpleAsync() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);
		executor.setMaxPoolSize(maxPoolSize);
		executor.setQueueCapacity(queueCapacity);
		executor.setThreadNamePrefix("MySimpleExecutor-");
		executor.initialize();
		return executor;
	}
	
	@Bean
	public Executor myAsync() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);
		executor.setMaxPoolSize(maxPoolSize);
		executor.setQueueCapacity(queueCapacity);
		executor.setThreadNamePrefix("MyExecutor-");

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

这里定义了两个不同的Executor,第二个重新设置了pool已经达到max size时候的处理方法;同时指定了线程名字的前缀。

2、自定义Executor的使用:

@Component
public class AsyncTask {
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Async("mySimpleAsync")
	public Future<String> doTask1() throws InterruptedException{
		logger.info("Task1 started.");
		long start = System.currentTimeMillis();
        Thread.sleep(5000);
        long end = System.currentTimeMillis();
        
        logger.info("Task1 finished, time elapsed: {} ms.", end-start);
        
        return new AsyncResult<>("Task1 accomplished!");
	}
	
	@Async("myAsync")
	public Future<String> doTask2() throws InterruptedException{
		logger.info("Task2 started.");
		long start = System.currentTimeMillis();
        Thread.sleep(3000);
        long end = System.currentTimeMillis();
        
        logger.info("Task2 finished, time elapsed: {} ms.", end-start);
        
        return new AsyncResult<>("Task2 accomplished!");
	}
}

就是把上面自定义Executor的类名,放进@Async注解中。

3、(测试用例不变)测试结果:

2016-12-13 10:57:11,998:INFO MySimpleExecutor-1 (AsyncTask.java:22) - Task1 started.
2016-12-13 10:57:12,001:INFO MyExecutor-1 (AsyncTask.java:34) - Task2 started.
2016-12-13 10:57:15,007:INFO MyExecutor-1 (AsyncTask.java:39) - Task2 finished, time elapsed: 3000 ms.
2016-12-13 10:57:16,999:INFO MySimpleExecutor-1 (AsyncTask.java:27) - Task1 finished, time elapsed: 5001 ms.
2016-12-13 10:57:17,994:INFO main (TaskTests.java:23) - Task1 result: Task1 accomplished!
2016-12-13 10:57:17,994:INFO main (TaskTests.java:24) - Task2 result: Task2 accomplished!
2016-12-13 10:57:17,994:INFO main (TaskTests.java:30) - All tasks finished.
2016-12-13 10:57:18,064 Thread-3 WARN Unable to register Log4j shutdown hook because JVM is shutting down. Using SimpleLogger

可见,线程名字的前缀变了,两个task使用了不同的线程池了。

参考博客:http://blog.csdn.net/clementad/article/details/53607311

© 著作权归作者所有

共有 人打赏支持
weiliu007
粉丝 14
博文 171
码字总数 84766
作品 0
深圳
程序员
Spring Boot系列二 Spring @Async异步线程池用法总结

. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调...

Canaan_
04/07
0
3
SpringBoot | 第二十一章:异步开发之异步调用

前言 上一章节,我们知道了如何进行异步请求的处理。除了异步请求,一般上我们用的比较多的应该是异步调用。通常在开发过程中,会遇到一个方法是和实际业务无关的,没有紧密性的。比如记录日...

oKong
前天
0
0
SpringBoot | 第二十章:异步开发之异步请求

前言 关于的相关知识点,后续有补充时再开续写了。比如服务、等,这些一般上觉得不完全属于方面的,而且目前作为一个接口来提供服务的机会应该比较小了吧。所以本章节开始,开始讲解关于异步...

oKong
08/16
0
0
Spring Boot Async异步执行

异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑。 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代...

尹吉欢
2017/12/13
0
0
Spring Boot 1.X和2.X优雅重启实战

项目在重新发布的过程中,如果有的请求时间比较长,还没执行完成,此时重启的话就会导致请求中断,影响业务功能,优雅重启可以保证在停止的时候,不接收外部的新的请求,等待未完成的请求执行...

尹吉欢
05/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Memcached启动参数详解

memcached -d -m 1024 -l 192.168.100.101 -p 11211 -P /tmp/memcached.pid -c 1024 -f 1.25 -n 80 -t 16 运行参数描述 -d:以守护(daemon)进程方式启动; -u:是运行Memcache的用户,例如 ......

月下狼
14分钟前
0
0
xgboost-kaggle

https://www.kaggle.com/dansbecker/xgboost This tutorial is part of the Learn Machine Learning series. In this step, you will learn how to build and optimize models with the powe......

tantexian
15分钟前
0
0
nginx学习八 代理服务

最常用的语法 proxy_pass Syntax: proxy_pass URL;Default: --Context:location.if in location,limit_exception 反向代理 例:/etc/nginx/conf.d/default.conf 反向代理(代理服务端)......

Romanceling
22分钟前
0
0
npm ERR! Unexpected end of JSON ...

npm install 报错: npm ERR! Unexpected end of JSON input while parsing near '..."^2.8.14"},"_hasShrin' npm ERR! A complete log of this run can be found in: ... 打开终端 命令: 第......

大_侠
26分钟前
0
0
Android中的设计模式之责任链模式

参考 《设计模式:可复用面向对象软件的基础 》5.1 Chain of responsibility 职责链 对象行为型模式 《Android源码设计模式解析与实战》第9章 使编程更有灵活性--责任链模式 意图 使多个对象...

newtrek
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部