概念
异步调用
Spring提供了Async注解来实现方法的异步调用。
即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行此方法。
这种异步执行的方式通常用于处理接口中不需要返回给用户的数据处理。比如当注册的时候,只需要将用户信息返回用户,而关于信息的保存操作可以使用异步执行。
定时任务
Spring提供了Scheduled注解来实现定时任务的功能。
在异步方法和定时任务功能中都是开发这自己定义需要执行的方法,然后交给Spring容器管理线程,并执行相应的方法。在使用异步方法和定时任务的时候需要特别注意的是线程池的配置以及任务中异常的处理。
定时任务
定时任务配置
新建ScheduleConfig类
package com.hyn.spring.config;
import java.util.concurrent.Executors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
/**
* 配置定时任务线程池
* @Title: ScheduleConfig.java
* @Package com.summit.tas.cfg
* @Description: TODO
* @author hyn
* @date 2019年1月5日 上午10:55:54
* @version V1.0
*/
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//设定一个长度的定时任务线程池
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
在启动类加上 @EnableScheduling 注解。
新建MyScheduleTask类:
package com.hyn.spring.schedule;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyScheduleTask {
@Scheduled(cron = "0/5 * * * * ? ")
public void task1() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("task1 thread name is :"+Thread.currentThread().getName()+"-"+dateFormat.format(new Date()));
}
@Scheduled(cron = "0/5 * * * * ? ")
public void task2() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("task2 thread name is :"+Thread.currentThread().getName()+"-"+dateFormat.format(new Date()));
}
}
异步调用
配置
新建AsynConfigurer类
package com.hyn.spring.config;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class AsynConfigurer implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
// 返回值为void的异步方法不会传递异常,当方法中出现异常的时候只会打印日志,重写此方法来自定义异常处理方法
return null;
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor asyncTaskThreadPool = new ThreadPoolTaskExecutor();
asyncTaskThreadPool.setCorePoolSize(100);
asyncTaskThreadPool.setMaxPoolSize(200);
asyncTaskThreadPool.setQueueCapacity(20);
asyncTaskThreadPool.setThreadFactory(new ThreadFactory() {
private final AtomicLong index = new AtomicLong(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "Async-override-task-pool-thread-" + index.getAndIncrement());
}
});
asyncTaskThreadPool.initialize();
return asyncTaskThreadPool;
}
}
启动类加上:@EnableAsync注解
方法加上@Async
package com.hyn.spring.schedule;
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
@Component
public class MyAsynTask {
@Async
public Future<String> asyncTaskWithResult(String name) {
System.out.println(name+"AsyncTaskWithResult start.");
try {
Thread.sleep(1000 * 10);
} catch (Exception e) {
return new AsyncResult<>("error" + e.getMessage());
}
System.out.println("AsyncTaskWithResult finished.");
return new AsyncResult<>("success");
}
}