在实际项目当中,经常用到异步处理,今天利用周末时间总结一下。
一、同步调用和异步处理的区别:
同步调用:整个处理过程按顺序执行,每一步必须等到上一步执行完后才能执行
异步调用:只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕,继续执行下面的流程。
异步实现方式
方式一:
1. new Thread((new Runnable() {
1. @Override
1. public void run() {
1. // 批量同步数据
1. try {
1. logger.info("^^^^^^^^^^^^^^^^^ sync start ^^^^^^^^^^^^^^^^^ ");
1.
1. logger.info("^^^^^^^^^^^^^^^^^ sync end ^^^^^^^^^^^^^^^^^ ");
1. } catch (IOException e) {
1. LogUtils2.error("", e);
1. }
1. }
1. })).start();
方式2:
private ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
@Override
public void run() {
// 批量同步数据
try {
logger.info("^^^^^^^^^^^^^^^^^ sync weinxi data start ^^^^^^^^^^^^^^^^^ ");
weiXinUsersService.batchSaveHandle();
logger.info("^^^^^^^^^^^^^^^^^ sync weinxi data end ^^^^^^^^^^^^^^^^^ ");
} catch (IOException e) {
LogUtils2.error("", e);
}
}
});
方式3:@EnableAsync和@Async注解
- 异步注解 @EnableAsync :开启异步方法的支持
- @Async 异步方法
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AsyncConfigurationSelector.class})
public @interface EnableAsync {
Class<? extends Annotation> annotation() default Annotation.class;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
@EnableAsync用于开启异步方法的支持。只有开启了异步方法的支持才可以使用@Async`。
一、开启异步:@ENABLEASYNC
@EnableAsync
@SpringBootApplication
public class Application {
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
@EnableAsync可以让Spring启用异步方法执行,就跟在xml中配置task:* 效果是一样的。它可以跟@Configuration结合,让整个Spring环境启用基于注解的异步处理:
import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@Configuration
@EnableAsync
@SuppressWarnings(value = "Duplicates")
public class AppConfig {
public static final String ASYNC_EXECUTOR_NAME = "asyncExecutor";
@Bean(name=ASYNC_EXECUTOR_NAME)
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// for passing in request scope context
executor.setTaskDecorator(new ContextCopyingDecorator());
executor.setCorePoolSize(3);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(100);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize();
return executor;
}
@Bean
public Gson gson() {
return new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
}
为什么要给@ASYNC自定义线程池?
@Async注解,在默认情况下用的是SimpleAsyncTaskExecutor线程池,该线程池不是真正意义上的线程池,因为线程不重用,每次调用都会新建一条线程。
@Async注解异步框架提供多种线程
SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。
SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方
ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类
ThreadPoolTaskScheduler:可以使用cron表达式
ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对java.util.concurrent.ThreadPoolExecutor的包装
举例:
@EnableAsync
public class WeiXinUsersService extends BaseGongfuService {
@Async
public void batchSaveHandle() throws IOException
}
}
@Async`可以把某一个方法或者类下面的方法全部变成异步处理的方法。