Spring 通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可以实现一个基于线程池的TaskExecutor。而实际上开发中的任务一般是非阻塞的,即异步的,所以我们要在配置类中通过@EnableAsync注解来开启对异步任务的支持,并通过在实际执行的Bean的方法上使用@Async注解来声明一个异步任务。
配置类:
package com.chenfeng.xiaolyuh.thread.config;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration // 声明当前类是一个配置类,相当于Spring配置的XML文件
@ComponentScan(basePackages={"com.chenfeng.xiaolyuh.thread"})
@EnableAsync// 利用@EnableAsync注解开启异步任务的支持
// 配置类实现AsyncConfigurer接口并重写getAsyncExecutor方法,并返回ThreadPoolTaskExecutor,这样我们就获得了一个基于线程池TaskExecutor
public class ThreadConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 核心线程数
taskExecutor.setCorePoolSize(5);
// 最大线程数
taskExecutor.setMaxPoolSize(50);
// 队列最大长度
taskExecutor.setQueueCapacity(1000);
// 线程池维护线程所允许的空闲时间(单位秒)
taskExecutor.setKeepAliveSeconds(120);
// 线程池对拒绝任务(无线程可用)的处理策略 ThreadPoolExecutor.CallerRunsPolicy策略 ,调用者的线程会执行该任务,如果执行器已关闭,则丢弃.
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
taskExecutor.initialize();
return taskExecutor;
}
@Bean
public Executor getThreadPool() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(1000);
taskExecutor.setQueueCapacity(1000);
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
任务执行类:
package com.chenfeng.xiaolyuh.thread.service;
import java.util.concurrent.Executor;
import javax.annotation.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* 多线程的测试类
* @ClassName DemoELService
* @author yuhao.wang
* @Date 2017年3月10日 下午3:41:18
* @version 1.0.0
*/
@Service
public class DemoThreadService {
@Resource(name = "getThreadPool")
private Executor executor;
@Async
// 通过@Async注解方法表名这个方法是一个异步方法,如果注解在类级别,则表名该类的所有方法都是异步的,
// 而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
public void executeAsyncTask(Integer i) {
System.out.println("执行异步任务:" + i);
}
public void executeAsyncTaskPlus(Integer i) {
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("执行异步任务+1:" + i);
}
});
}
}
测试方法:
package com.chenfeng.xiaolyuh.test;
import org.junit.After;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.chenfeng.xiaolyuh.thread.config.ThreadConfig;
import com.chenfeng.xiaolyuh.thread.service.DemoThreadService;
/**
* Created by yuhao.wang on 2017/3/9.
*/
public class SpringThreadTest {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ThreadConfig.class);
@Test
public void contextTest() {
DemoThreadService demoThreadService = context.getBean(DemoThreadService.class);
for (int i = 0; i < 1000; i++) {
demoThreadService.executeAsyncTaskPlus(i);
demoThreadService.executeAsyncTask(i);
}
}
@After
public void closeContext() {
context.close();
}
}
ThreadPoolTaskExecutor相关知识: http://www.cnblogs.com/lic309/p/4186880.html
ThreadPoolExecutor 相关知识:http://blog.csdn.net/wenhuayuzhihui/article/details/51377174