博客详情

springboot中开启@Async异步支持 (原创)

作者: 朝如青丝暮成雪
发布时间:2019-12-26 13:30:59  文章分类:springboot   阅读(1390)  评论(0)

springboot中开启@Async异步支持:

其实,@Async的异步调用从spring3.x之后就开始支持了,springboot中当然也可以使用。


1、配置AsyncConfig配置类


package com.tingcream.springmybatis.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@EnableAsync//开启Async异步调用支持
@Configuration
public class AsyncConfig {

	/**
	 * 自定义异步线程的执行器 ,springboot中默认寻找的执行器名称为"taskExecutor"
	 */
	@Bean
	public TaskExecutor taskExecutor() {
	        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
	        // 设置核心线程数
	        executor.setCorePoolSize(10);
	        // 设置最大线程数
	        executor.setMaxPoolSize(20);
	        // 设置队列容量
	        executor.setQueueCapacity(20);
	        // 设置线程活跃时间(秒)
	        executor.setKeepAliveSeconds(60);
	        // 设置线程名称前缀
	        executor.setThreadNamePrefix("async-task-thread-");
	        return executor;
	}
}


2、AsyncController(测试controller层)


package com.tingcream.springmybatis.async.controller;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tingcream.springmybatis.async.service.AsyncService;
import com.tingcream.springmybatis.common.RetMsg;

/**
 * 异步调用测试 controller层
 * @author jelly
 */
@RestController
@RequestMapping("/async")
public class AsyncController {
	@Autowired
	private AsyncService asyncService ;
	

	@RequestMapping("/test1")
	public RetMsg<?> test1(String name) {
		
		 long  t1=System.currentTimeMillis();
		 Future<String> n = asyncService.getName(name);
		 Future<Integer> age =  asyncService.getAge();
		 Map<String,Object> map =new HashMap<String,Object>();
		 try {
			 map.put("name",  n.get());// 调用Feture<V>对象的get方法会产生阻塞,直到有结果返回
			 map.put("age",  age.get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
		 long  t2=System.currentTimeMillis();
		 long  sec= (t2-t1)/1000;
		 System.out.println("耗时:"+sec+"秒");
		 map.put("ts",sec+"秒"); //4秒
		return RetMsg.success(map);
	}
}
3、AsyncService(测试service层)



package com.tingcream.springmybatis.async.service;

import java.util.concurrent.Future;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

/**
 * 异步调用测试 service层
 * @author jelly
 *
 */
@Service
public class AsyncService {

	@Async
	public Future<String>  getName(String name) {
		try {
			 System.out.println("线程名:"+Thread.currentThread().getName());
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//  return AsyncResult.forValue("hi:"+name) ;
		 return new AsyncResult<>("hi:"+name);
	}
	
	@Async
	public Future<Integer> getAge() {
		try {
			System.out.println("线程名:"+Thread.currentThread().getName());
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 return new AsyncResult<>(22);
	}

}


浏览器请求: http://localhost:8081/async/test1?name=zhangsan  

控制台输出:


4、附:关于线程池的执行及任务代理



@Async注解中还可以指定value的值,可通过bean名称来指定调用的线程池, springboot默认会使用名称为"taskExecutor"的线程池,如果没有找到,才会使用其他类型为TaskExecutor或其子类的线程池。例如:@Async("MyExecutor") 就可以改为使用其他的线程池对象去执行异步任务。

spring中的线程执行器

Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象。 Spring的TaskExecutor和java.util.concurrent.Executor接口时一样的,这个接口只有一个方法execute(Runnable task)。 Spring已经内置了许多TaskExecutor的实现,没有必要自己去实现: 1、SimpleAsyncTaskExecutor 这种实现不会重用任何线程,每次调用都会创建一个新的线程。 2、SyncTaskExecutor 这种实现不会异步的执行 3、ConcurrentTaskExecutor 这种实现是java.util.concurrent.Executor的一个adapter。 4、SimpleThreadPoolTaskExecutor 这种实现实际上是Quartz的SimpleThreadPool的一个子类,它监听Spring的声明周期回调。 5、ThreadPoolTaskExecutor 这是最常用最通用的一种实现。它包含了java.util.concurrent.ThreadPoolExecutor的属性,并且用TaskExecutor进行包装。

spring中async代理对象

在spring中,@Async注解既可以标记在类上也可以标记在方法上。如果标记在类上则表示类中的所有方法均为异步的(相当于所有的类中所有方法都标记了@Async主机),标记在方法上则此方法时异步的。无论是标记在类上还是方法上,类中只要有一个标记了@Async注解,spring都会为这个bean创建动态代理对象,这个代理对象会寻找线程执行器从而启动一个线程来执行方法中的内容。由于代理对象是基于bean来动态创建而不是基于bean的每个方法创建的,因此在@Async的bean中,异步A方法中调用异步的B方法,仍然是同步调用的。







关键字:  Async  springboot  异步调用
评论信息
暂无评论
发表评论

亲,您还没有登陆,暂不能评论哦! 去 登陆 | 注册

博主信息
   
数据加载中,请稍候...
文章分类
   
数据加载中,请稍候...
阅读排行
 
数据加载中,请稍候...
评论排行
 
数据加载中,请稍候...

Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1

鄂公网安备 42011102000739号