Spring线程池ThreadPoolTaskExecutor配置及详情
属性字段说明
corePoolSize:线程池维护线程的最少数量
keepAliveSeconds:允许的空闲时间
maxPoolSize:线程池维护线程的最大数量
queueCapacity:缓存队列
rejectedExecutionHandler:对拒绝task的处理策略
execute(Runable)方法执行过程
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
示例:
/**
* 多线程并发处理demo
*/
public class MultiThreadDemo implements Runnable {
public MultiThreadDemo() {
}
@Override
public void run() {
System.out.println("测试");
}
}
/**
*线程池配置类
*/
@Component
public class TaskExecutePool {
//最小线程数
private int corePoolSize = 50;
//最大线程数
private int maxPoolSize = 1000;
//连接空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "taskExecutor")
public ThreadPoolTaskExecutor myTaskExecutePool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setThreadNamePrefix("MyExecutor-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
//测试类
public class MultiThreadTest {
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Test
public void test() {
int n = 20;
for (int i = 0; i < n; i++) {
taskExecutor.execute(new MultiThreadDemo());
}
}
}
该线程池可以搭配FutureTask和Callable组合使用,更加灵活
Callable接口:实现这个接口的类,可以在这个类中定义需要执行的方法和返回结果类型。
//MyTask.java类
public class MyTask implements Callable<Object>{
private String args1;
private String args2;
//构造函数,用来向task中传递任务的参数
public MyTask(String args1,String args2) {
this.args1=args1;
this.args2=args2;
}
//任务执行的动作
@Override
public Object call() throws Exception {
for(int i=0;i<100;i++){
System.out.println(args1+args2+i);
}
return true;
}
}
FutureTask使用方法
public static void main(String[] args) {
MyTask myTask = new MyTask("11", "22");//实例化任务,传递参数
FutureTask<Object> futureTask = new FutureTask<>(myTask);//将任务放进FutureTask里
//采用thread来开启多线程,futuretask继承了Runnable,可以放在线程中来启动执行
Thread thread = new Thread(futureTask);
thread.start();
try {
//get():获取任务执行结果,如果任务还没完成则会阻塞等待直到任务执行完成。如果任务被取消则会抛出CancellationException异常,
//如果任务执行过程发生异常则会抛出ExecutionException异常,如果阻塞等待过程中被中断则会抛出InterruptedException异常。
boolean result = (boolean) futureTask.get();
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
与ThreadPoolTaskExecutor线程池组合使用
public static void main(String[] args) {
//创建一个FutureTask list来放置所有的任务
List<FutureTask<Object>> futureTasks=new ArrayList<>();
for(Integer i=0;i<10;i++){
MyTask myTask=new MyTask(i.toString(), i.toString());
futureTasks.add(new FutureTask<>(myTask));
}
//创建线程池后,依次的提交任务,执行
ThreadPoolTaskExecutor myTaskExecutePool = new ThreadPoolTaskExecutor();
for(FutureTask<Object> futureTask:futureTasks){
myTaskExecutePool .execute(futureTask);
}
//根据任务数,依次的去获取任务返回的结果,这里获取结果时会依次返回,若前一个没返回,则会等待,阻塞
for(Integer i=0;i<10;i++){
try {
String flag=(String)futureTasks.get(i).get();
System.out.println(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
}