@Async异步

@Async异步

一 、异步与同步

异步:当程序1调用程序2时,程序1继续自己下面的动作,不受程序2的影响;

同步:当程序1调用程序2时,程序1停下不动,直到程序2完成回到程序1来,程序1才继续执行下去;

或者

异步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事;(AJAX技术)

同步:请求通过事件触发->服务器处理(期间浏览器仍然可以作其他事情)->处理完毕;(普通B/S模式)

@Async异步_第1张图片

二、Spring中的@Async

Spring中,默认采用的是单线程的模式,在java应用中,绝大数情况都是通过同步的方式实现交互处理的;

但是当多个任务的执行肯定会相互影响,例如:在同一个请求方法中,如果A任务执行时间比较长,B任务必须等到A任务执行完毕之后才会执行。又比如在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,现在就直接可以使用spring内置的@Async注解来解决此问题;

三、@Async注解使用

  1. @Async注解一般用在类的方法上,如果用在类上,那么这个类所有的方法都是异步执行的;
  2. 所使用的@Async注解方法的类对象应该是Spring容器管理的bean;
  3. 调用异步方法类上需要配置上注解@EnableAsync

使用注意:

  1. 默认情况下(即@EnableAsync注解的mode=AdviceMode.PROXY),同一个类内部没有使用@Async注解修饰的方法调用@Async注解修饰的方法,是不会异步执行的,这点跟 @Transitional 注解类似,底层都是通过动态代理实现的。如果想实现类内部自调用也可以异步,则需要切换@EnableAsync注解的mode=AdviceMode.ASPECTJ
  2. 方法返回值必须是void或者Future类型。当使用Future时,可以使用实现了Future接口的ListenableFuture接口或者CompletableFuture类与异步任务做更好的交互。如果异步方法有返回值,没有使用Future类型的话,调用方获取不到返回值。
  3. @Async 必须不同类之间调用:A类–》B类.C方法()(@Async注释在B类/方法中),如果在同一个类中调用,会变同步执行,例如:A类.B()–>A类.@Async C(),原因是:底层实现是代理对注解扫描实现的,B方法上没有注解,没有生成相应的代理类。

源码就先不研究了,其实看了源码就会发现这样一个结果:@Async底层使用的是线程池技术。

想要查看源码可以看这篇文章:https://blog.csdn.net/fenglongmiao/article/details/82429460

四、@Async测试

首先执行类上配置上@EnableAsync注解;

conroller类:

package com.leejie.controller;

import com.leejie.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @Autowired
    private TestService service;

    @GetMapping("hello")
    public String hello(){
        service.hello();
        System.out.println("主程序结束....");
        return "test is over...";
    }
}

service类:

package com.leejie.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    @Async("taskExecutor")
    public void hello(){
        System.out.println("serviceMethod执行....");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("睡眠结束....");
    }
}

自定义Executor:

package com.leejie.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class MyExecutor {
    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        System.out.println("创建自定义Executor...");
        // 核心线程数
        executor.setCorePoolSize(20);
        // 最大线程数
        executor.setMaxPoolSize(50);
        // 队列最大长度
        executor.setQueueCapacity(100);
        // 线程池维护线程所允许的空闲时间
        executor.setKeepAliveSeconds(100);
        // 线程前缀
        executor.setThreadNamePrefix("AsyncExecutorThread-");
        // 线程池对拒绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

运行项目,调用接口会发现:页面直接返回结果,而不会等待service方法执行完再返回结果。

@Async异步_第2张图片
**总结:**我觉得主要了解一下异步执行的含义和相关简单的特性以及基本原理,熟悉底层原理的话还是需要对springboot底层,设计模式等知识熟悉才行;下来可以在了解一下Executor框架;

你可能感兴趣的:(sync异步,spring,boot,java)