Spring异步任务处理,@Async的配置和使用

这个注解用于标注某个方法或某个类里面的全部方法都是须要异步处理的。被注解的方法被调用的时候。会在新线程中运行,而调用它的方法会在原来的线程中运行。

这样能够避免堵塞、以及保证任务的实时性。适用于处理log、发送邮件、短信……等。

注解的应用范围:

  • 类:表示这个类中的全部方法都是异步的
  • 方法:表示这种方法是异步的,假设类也注解了。则以这种方法的注解为准

相关的配置:

<task:annotation-driven />配置:

  • executor:指定一个缺省的executor给@Async使用。

样例:

<task:annotation-driven executor="asyncExecutor" />

<task:executor />配置參数:

  • id:当配置多个executor时,被@Async("id")指定使用;也被作为线程名的前缀。
  • pool-size
    • core size:最小的线程数。缺省:1
    • max size:最大的线程数,缺省:Integer.MAX_VALUE
  • queue-capacity:当最小的线程数已经被占用满后,新的任务会被放进queue里面,当这个queue的capacity也被占满之后,pool里面会创建新线程处理这个任务。直到总线程数达到了max
    size,这时系统会拒绝这个任务并抛出TaskRejectedException异常(缺省配置的情况下,能够通过rejection-policy来决定怎样处理这样的情况)。缺省值为:Integer.MAX_VALUE
  • keep-alive:超过core size的那些线程,任务完毕后,再经过这个时长(秒)会被结束掉
  • rejection-policy:当pool已经达到max size的时候,怎样处理新任务
    • ABORT(缺省):抛出TaskRejectedException异常,然后不运行
    • DISCARD:不运行,也不抛出异常
    • DISCARD_OLDEST:丢弃queue中最旧的那个任务
    • CALLER_RUNS:不在新线程中运行任务,而是有调用者所在的线程来运行

配置样例:

<task:annotation-driven executor="asyncExecutor" />

<task:executor id="asyncExecutor" pool-size="100-10000" queue-capacity="10"/>

实例:

 <!-- 缺省的异步任务线程池 -->
 <task:annotation-driven executor="asyncExecutor" />
 <task:executor id="asyncExecutor" pool-size="100-10000" queue-capacity="10" />

 <!-- 处理log的线程池 -->
 <task:executor id="logExecutor" pool-size="15-1000" queue-capacity="5" keep-alive="5"/>
 @Override
 @Async("logExecutor")    //假设不指定名字。会使用缺省的“asyncExecutor”
 public void saveUserOpLog(TabUserOpLog tabUserOpLog) {

  userOpLogDAO.insertTabUserOpLog(tabUserOpLog);
 }

(注意:假设在同一个类中调用的话。不会生效,原因请參考:http://blog.csdn.net/clementad/article/details/47339519

通过log能够看到,已经分开两个线程运行:

线程的优先级和类型:

优先级:NORM_PRIORITY

类型:非守护线程

用户线程(User Thread):JVM会等待全部的用户线程结束后才退出;当系统中没实用户线程了,JVM也就退出了

守护线程(Daemon Thread):通常是为其它线程提供服务的线程。比方GC垃圾回收器;JVM退出时,不会管守护线程是否存在,而是直接退出

所以,对于文件、数据库的操作。不适宜使用守护线程,不然可能会丢失数据!

Web应用停止时,Spring容器会被关闭。调用者假设是Spring bean。就会停止生成新任务。

然而,线程池中已经在执行的任务。因为缺省是用户线程,所以JVM会等待它们结束后才退出。

附:Java编程方式的配置方法:

@Configuration
@EnableAsync
public class SpringConfig {

	/** 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;

	private String ThreadNamePrefix = "MyLogExecutor-";

	@Bean
	public Executor logExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);
		executor.setMaxPoolSize(maxPoolSize);
		executor.setQueueCapacity(queueCapacity);
		executor.setThreadNamePrefix(ThreadNamePrefix);

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

}

(原创文章。转载请注明转自Clement-Xu的博客:http://blog.csdn.net/clementad/article/details/47403185

时间: 2024-11-04 10:04:44

Spring异步任务处理,@Async的配置和使用的相关文章

Spring异步执行(@Async)2点注意事项

Spring中可以异步执行代码,注解方式是使用@Async注解. 原理.怎么使用,就不说了. 写2点自己遇到过的问题. 1.方法是公有的 // 通知归属人 @Async public void notifyPusher(Project project) { } 2.异步代码,需要放在外部单独的类中. @Service("asyncBiz")public class AsyncBiz { @Async public void notifyPusher(Project project) {

工作随笔——spring异步处理@Async使用笔记

@Async使用笔记 必须是public方法 必须是非static方法 方法调用的实例必须由spring创建和管理 代码示例如下: // 创建Foo类@Component class Foo { @Async public static void bar(){ /* ... */ } @Async public void bar2(){ /* ... */ } } // 调用示例代码class Test { @Autowired //@Lazy(true)可以解决spring循环引用的问题 Fo

Spring异步调用原理及SpringAop拦截器链原理

一.Spring异步调用底层原理 开启异步调用只需一个注解@EnableAsync @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AsyncConfigurationSelector.class) public @interface EnableAsync { /** * Indicate the 'async' annotation type to be detected at

Spring中的@Async

在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题 1.  何为异步调用? 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果. 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕:而是继续执行下面的流程. 例如, 在某个调用中

Spring Boot中@Async的作用

在Spring中,@Async这个注解用于标记的异步的方法.方法上一旦标记了这个方法,当其它线程调用这个方法时,就会开启一个新的线程去异步处理业务逻辑. 此注解的使用说明: 1.此注解可以用在方法上,也可以用在类上(如果用在类上,这个类中的所有的方法就是异步的) 2.使用此注解的方法的类对象,需要是spring管理下的bean对象 3.程序主类或此注解的主类上,需要开启启用异步配置,配置上@EnableAsync注解 以Spring boot 为例,启动类中增加@EnableAsync, @En

Spring boot 注解@Async

从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法.调用者将在调用时立即返回,方法的实际执行将提交给Spring TaskExecutor的任务中,由指定的线程池中的线程执行. 1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池:1. SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线

Android笔记二十六.Android异步任务处理(AsyncTask)

转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) 一.引言 我们知道Android的UI线程主要负责处理用户的按键事件.用户触屏事件及屏幕绘图事件等,对于其他的操作尽量不要在UI线程中实现,因为这些操作很有可能会阻塞UI线程,比如一些耗时操作,会导致UI界面停止响应,从而降低了用户的体验.所以,为了避免UI线程失去响应的问题,Android建议将耗时操作放在新线程中完成,但新线程也可能需要动态更新UI组件:比如需要从网上获取一个网页,然后在Te

在tornado中使用celery实现异步任务处理之一

一.简介 tornado-celery是用于Tornado web框架的非阻塞 celery客户端. 通过tornado-celery可以将耗时任务加入到任务队列中处理, 在celery中创建任务,tornado中就可以像调用AsyncHttpClient一样调用这些任务. ? Celery中两个基本的概念:Broker.Backend Broker : 其实就是一开始说的 消息队列 ,用来发送和接受消息. Broker有几个方案可供选择:RabbitMQ,Redis,数据库等 Backend:

spring异步执行报异常No qualifying bean of type &#39;org.springframework.core.task.TaskExecutor&#39; available

最近观察项目运行日志的时候突然发现了一个异常, [2018-04-03 10:49:07] 100.0.1.246 http-nio-8080-exec-9 DEBUG org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor---- Could not find default TaskExecutor bean org.springframework.beans.factory.NoSuchBe