- @Async注解来声明一个或多个异步任务,可以加在方法或者类上,加在类上表示这整个类都是使用这个自定义线程池进行操作,没有自定义线程池@Async默认的线程池是SimpleAsyncTaskExecutor
- 基于@Async标注的方法,称之为异步方法,这个注解用于标注某个方法或某个类里面的所有方法都是需要异步处理的。被注解的方法被调用的时候,会在新线程中执行,而调用它的方法会在原来的线程中执行
参数 |
描述 |
value |
指定异步操作的限定符值。 可用于确定执行异步操作时要使用的目标执行器,与特定执行器或TaskExecutor bean定义的限定符值(或bean名称)匹配。 在类级别@Async注释上指定时,表示给定的执行器应用于类中的所有方法。方法级使用异步#值总是覆盖在类级设置的任何值。 |
- application.xml
<!--扫描注解,其中包括@Async --> <context:component-scan base-package="com.test" /> <!-- 支持异步方法执行, 指定一个缺省的executor给@Async使用--> <task:annotation-driven executor="defaultAsyncExecutor" /> <task:executor id="defaultAsyncExecutor" pool-size="100-10000" queue-capacity="10" keep-alive="”5”" /> |
解析
<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 |
不在新线程中执行任务,而是有调用者所在的线程来执行 |
注
- 异步方法不能与异步方法在同一个类中,异步方法不能使用static修饰
- 使用@Async时要求是不能有返回值
- 调用被@Async标记的方法不能和调用方法在同一类中
示例
- testAsyncVoid.java
//在类或方法上添加@Async,当调用该方法时,则该方法即是用异常执行的方法单独开个新线程执行
@Async(“可以指定执行器id,也可以不指定”)
public static void testAsyncVoid(){
try{
//让程序暂停100秒,相当于执行一个很耗时的任务
System.out.println(“异常执行打印字符串”);
Thread.sleep(100000);
}
catch (InterruptedException e){
e.printStackTrace();
}
}
- 当在外部调用testAsync方法时即在新线程中执行,由上面<task: annotation-driven/>执行器去维护线程
- 并可以指定默认的线程执行器executor。那么当用@Async注解的方法或类得到调用时,线程执行器会创建新的线程去执行