spring学习(二十七)--@Async

Posted on 2019-11-07 23:38  GLLegolas  阅读(147)  评论(0编辑  收藏  举报

在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题。

1.  何为异步调用?

    在解释异步调用之前,我们先来看同步调用的定义;同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。

     例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法;如他们都是同步调用,则需要将他们都顺序执行完毕之后,方算作过程执行完毕; 如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了。

2.  常规的异步调用处理方式

    在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。或是使用TaskExecutor执行异步线程。

3. @Async介绍

   在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。

   如何在Spring中启用@Async。基于Java配置的启用方式:在类上使用@Component、@EnableAsync,在类中的方法上使用@Async注解,那么该方法在被调用的时候就会在开辟的新线程中异步执行。

package springAnnotions;

import java.util.concurrent.Future;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

/**
 * 开发多线程代码,有三种方法
 * 1、实现Runnable接口的run方法
 * 2、继承Thread接口重写run方法
 * 3、使用Callable和Future接口创建线程,这种可以获取返回值
 * 在spring中,使用@Aysnc可以被当作新的多线程方法,被@Aysnc注解的方法再被调用的时候,都会在新的线程中执行。
 * @author qiaozhong
 */
@Component
@EnableAsync
public class AsyncAnnotion {

    /**
     * 无返回值的异步方法
     * @param i
     */
    @Async
    public void asyncTest(String i){
        try {
            System.out.println(i + "start!");
            Thread.sleep(1000);
            System.out.println(i + "end!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 有返回值的异步方法
     * @param i
     * @return
     */
    @Async
    public Future<String> asyncReturnTest(String i){
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>(i);
    }
    
    /**
     * 无返回值的同步方法
     * @param i
     */
    public void notAsyncTest(String i){
        try {
            System.out.println(i + "start!");
            Thread.sleep(1000);
            System.out.println(i + "end!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springConfig/spring-all.xml");
        AsyncAnnotion asyncAnnotion = (AsyncAnnotion)ac.getBean(AsyncAnnotion.class);
        for (int i = 0; i < 3; i++) {
            asyncAnnotion.asyncTest(String.valueOf(i));
        }
        
        Thread.sleep(2000);
        
        for (int i = 0; i < 3; i++) {
            asyncAnnotion.notAsyncTest(String.valueOf(i));
        }
        
        Future<String> future;
        future = asyncAnnotion.asyncReturnTest(String.valueOf(5));
        do {
            if (future.isDone()) {
                try {
                    System.out.println(future.get());
                    break;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } while (true);
    }
    
}

 

执行main函数结果:

2start!
0start!
1start!
0end!
1end!
2end!
0start!
0end!
1start!
1end!
2start!
2end!
5