spring中异步方法的配置

1、把方法放在一个单独的service类中,用@Async标注方法,用@EnableAsync标注类。也可以用@Async标注service类。

这个时候,这个方法就是异步方法了,调用时会异步执行。但是,每执行一次这个方法都要生成一个线程(线程名以"SimpleAsyncTaskExecutor-"开头),执行完之后线程再销毁。这样很不好,最好有一个线程池,每次方法执行的时候都从线程池中取线程,执行完之后再放回到线程池中。这就有了第2步。

2、在applicationContext.xml中配置一个ExecutorService实例。方法有很多种,以下只是其中一种:

    <bean id="asyncThreadPoolExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="20"/>
<property name="maxPoolSize" value="40"/>
<property name="keepAliveSeconds" value="0"/>
<property name="queueCapacity" value="3000"/>
<property name="threadNamePrefix" value="asyncThreadPool-"/>
</bean>

如果不用上述方法显式地创建线程池,则也可以在applicationContext.xml文件中配置

 <task:executor id="annotationExecutor" pool-size="20-40" queue-capacity="3000" keep-alive="0" rejection-policy="ABORT"/>

这样就会产生一个ThreadPoolTaskExecutor实例。不过这种方式生成的线程池里的线程的名字不能像第一种方法那样自定义,而是固定以"annotationExecutor-"为开头的。

如果配置了多个<task:executor/>,则需要在配置@Async注解的时候,配置其value属性值为某个executorId,这样执行方法时就会使用这个指定的线程池,如@Async(value = "xxx"),否则不会用任何一个线程池,而是每执行一次就创建一个线程。

以上配置针对没有返回值的方法没问题,但是如果异步方法有返回值,而且想要获取该方法的返回值,那么这个异步方法就不能简简单单的返回原来想返回的值类型了,得返回xxxFuture<T>类型。阿里规约插件提醒如下:@Async methods should return void, java.util.concurrent.Future, org.springframework.util.concurrent.ListenableFuture or java.util.concurrent.CompletableFuture。

示例如下:

    @Async(value = "annotationExecutor")
public ListenableFuture<String> print() {
try {
Thread.sleep(3000);
LOGGER.info("async thread: " + Thread.currentThread().getName());
} catch (Exception e) {
LOGGER.error(e);
}
return new AsyncResult<String>("异步返回值");
}

AsyncResult全类名是org.springframework.scheduling.annotation.AsyncResult,实现了ListenableFuture接口。

需要特别提醒下, <task:annotation-driven/>这个跟异步没有半毛钱关系。跟定时任务有点关系,配置了的话,就不用@EnableScheduling注解了。

spring中定时任务的配置

1、用@Scheduled标注方法,用@EnableScheduling标注类,就可以了。

这时现在每执行一次定时任务,就会创建一个线程,执行完后销毁。需要引入线程池。这就需要第2步

2、在applicationContext.xml中配置如下:

    <bean id="scheduledThreadPoolExecutor" class="java.util.concurrent.ScheduledThreadPoolExecutor">
<constructor-arg name="corePoolSize" value="10"/>
<constructor-arg name="threadFactory" ref="threadFactory"/>
</bean>

并新建一个Config类(类名随便),内容如下:

@Configuration
public class Config {
@Bean("threadFactory")
public ThreadFactory getThreadFactory() {
return new ThreadFactoryBuilder().setNameFormat("scheduled-pool-%d").setPriority(10).setDaemon(false).build();
}
}

如果不用上述方法显式创建定时任务线程池,则还可以在applicationContext.xml中配置:

<task:scheduler id="scheduler" pool-size="5"/>

这种方法会生成一个指定大小的org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler实例。不过同样不能自定义线程名,线程名固定以"scheduler-"开头。

实际测试发现,如果既显式配置ScheduledExecutorService实例,又配置<task:scheduler/>的话,定时任务会用<task:scheduler/>对应的线程池。显示配置的ScheduledExecutorService实例没用。

最佳实践:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.google.common.util.concurrent.ThreadFactoryBuilder; @Configuration
public class Config { @Bean("asyncThreadPoolExecutor")
public ExecutorService getThreadPoolExecutor() {
return new ThreadPoolExecutor(20,
40,
0,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(3000),
new ThreadFactoryBuilder().setNameFormat("asyncThreadPool-%d").setPriority(10).setDaemon(false).build(),
new ThreadPoolExecutor.AbortPolicy());
} @Bean("scheduledThreadPoolExecutor")
public ScheduledExecutorService getThreadFactory() {
return new ScheduledThreadPoolExecutor(10,
new ThreadFactoryBuilder().setNameFormat("scheduledThreadPool-%d").setPriority(10).setDaemon(false).build(),
new ThreadPoolExecutor.AbortPolicy());
} }

spring对异步的支持的更多相关文章

  1. Java RMI 介绍和例子以及Spring对RMI支持的实际应用实例

    RMI 相关知识 RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网 ...

  2. Spring对jdbc支持

    4. Spring对jdbc支持 spring对jdbc提供了很好的支持 体现在: 1.Spring对C3P0连接池的支持很完善 2.Spring对jdbc提供了jdbcTemplate来简化jdbc ...

  3. 【杂谈】Spring Boot 默认支持的并发量

    Spring Boot应用支持的最大并发量是多少? Spring Boot 能支持的最大并发量主要看其对Tomcat的设置,可以在配置文件中对其进行更改.当在配置文件中敲出max后提示值就是它的默认值 ...

  4. Spring Batch JSON 支持

    Spring Batch 4.1 开始能够支持 JSON 格式了.这个发布介绍了一个新的数据读(item reader)能够读取一个 JSON 资源,这个资源按照下面的格式: [   {     &q ...

  5. 8 -- 深入使用Spring -- 4...4 Spring 的 AOP 支持

    8.4.4 Spring 的AOP 支持 Spring中的AOP代理由Spring的IoC容器负责生成.管理,器依赖关系也由IoC容器负责管理.因此,AOP代理可以直接使用容器中的其他Bean实例作为 ...

  6. Spring框架事务支持模型的优势

    全局事务 全局事务支持对多个事务性资源的操作,通常是关系型数据库和消息队列.应用服务器通过JTA管理全局性事务,API非常烦琐.UserTransaction通常需要从JNDI获取,意味着需要与JND ...

  7. spring对事务支持的三种形式

    spring对事务支持的三种形式: 1.通过spring配置文件进行切面配置 <bean id="***Manager" class="org.springfram ...

  8. Spring Boot 版本支持对应JDK

    转自:http://www.cnblogs.com/oumi/p/9241424.html 一.Spring Boot 版本支持 Spring Boot Spring Framework Java M ...

  9. spring注解不支持静态变量注入

    spring注解不支持静态变量注入:今天敲代码  自动配置 配置: Animal.java package study01_autoconfig.beanConfig; import org.spri ...

随机推荐

  1. 奇妙的 Storage::url

    发现 这是我在做头像上传功能时发现的,下面是图片上传的业务逻辑. class AvatarController extends Controller { public function update( ...

  2. Linux 查看是64位还是32位

    [root@VM_7_88_centos ~]# uname -a Linux VM_7_88_centos 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36: ...

  3. CSS3中的新特性

    一.CSS3新属性 CSS3还不属于W3C标准,所以不同浏览器的支持程度也不相同,对于不同浏览器,写法也不同,不同内核的浏览器要加不同的前缀,如下: transform:rotate(9deg); - ...

  4. JAVA的IO处理【转】

    I/O简介 IO是输入和输出的简称,在实际的使用时,输入和输出是有方向的.就像现实中两个人之间借钱一样,例如A借钱给B,相对于A来说是借出,而相对于B来说则是借入.所以在程序中提到输入和输出时,也需要 ...

  5. ExposedObject的使用

    ExposedObject可以将一个对象快速封装未一个dynamic using System; namespace ConsoleApp2 { class Program { static void ...

  6. 有关git的使用,和git的一些提交冲突。

    git 的一些基本用法 git init :初始化文件(创建文件夹). git add . :监控工作区的状态树(将被修改的文件提交到暂存区) git status :未跟踪状态(Untracked) ...

  7. Xamarin Forms:小马过河,王者归来

    因为我媳妇的原因,去年下半年从零开始学习Android原生开发,做了一个答题库app.整体给我的感觉是入门难度不大,前期折腾一番,大部分时间都是花在开发上面,其实任何一门语言都是如此. 今年我又有另一 ...

  8. SDUT OJ 数据结构实验之串三:KMP应用

    数据结构实验之串三:KMP应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descrip ...

  9. js appendChild与insertBefore 区别和用法

      1.appendChild() 方法:可以向节点的子节点列表的末尾添加新的子节点. 比如:appendChild(newchild)括号里可以是创建的标签var newchild = docume ...

  10. Rails应用系列(1):初识Rails

    第一个Rails应用 Rails是一个"模型-视图-控制器"框架(MVC).是用Ruby写的,所以要对Ruby要有一定的了解才能对rails框架深入学习.其实Ruby与Rails就 ...