@Async异步执行注解的使用

文章转载自:

@bladestone   https://blog.csdn.net/blueheart20/article/details/44648667#commentBox

@灵颖桥人   https://blog.csdn.net/qq_22076345/article/details/82194482

1.  何为异步调用?

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

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

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

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

3. @Async介绍

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

@Async注解使用条件:

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

 我们在Spring Boot项目中做一下测试,测试代码如下:

异步方法定义以及实现如下:

package com.qijie.demo.zqjhttpclient.service;

import org.springframework.scheduling.annotation.Async;

import java.util.concurrent.Future;

@Async
public interface TestService {

    void test();

}
package com.qijie.demo.zqjhttpclient.service.impl;

import com.qijie.demo.zqjhttpclient.service.TestService;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Service
public class TestServiceImpl implements TestService{

    public void test(){
        System.out.println("ThreadName:" + Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("测试Spring 异步调用!");
    }
}

调用异步方法的controller类代码如下:

package com.qijie.demo.zqjhttpclient.controller;

import com.qijie.demo.zqjhttpclient.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@EnableAsync
@RequestMapping(value = "/test")
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping(value = "/testAsync")
    public void print() {
        System.out.println("ThreadName:" + Thread.currentThread().getName());
        System.out.println("当前线程开始执行测试函数......");
        testService.test();
        for (int i = 1; i <= 100; i++) {
            System.out.print(i + " ");
            if (i % 10 == 0) {
                System.out.println();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("当前线程测试函数执行完毕......");
    }
}

程序启动后,浏览器访问http://localhost:8080/test/testAsync,后台打印日志如下:

可以看出是有两个线程在执行。如果我们去除TestController上的@EnableAsync或者new 一个TestService对象(该对象没有加载进Spring的容器中),那么TestController中的print()方法都会同步执行,后台打印日志也可以看到只有一个线程在执行。

4. 基于@Async无返回值调用

package com.qijie.demo.zqjhttpclient.service;

import org.springframework.scheduling.annotation.Async;

import java.util.concurrent.Future;

@Async
public interface TestService {

    void asyncMethodWithVoidReturnType();//基于@Async无返回值调用

    Future<String> asyncMethodWithReturnType();//基于@Async有返回值调用
}
package com.qijie.demo.zqjhttpclient.service.impl;

import com.qijie.demo.zqjhttpclient.service.TestService;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Service
public class TestServiceImpl implements TestService{

    public void asyncMethodWithVoidReturnType() {
        System.out.println("Execute method asynchronously. "
                + Thread.currentThread().getName());
    }

    public Future<String> asyncMethodWithReturnType() {
        System.out.println("Execute method asynchronously - "
                + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            return new AsyncResult<String>("hello world !!!!");
        } catch (InterruptedException e) {
            //
        }
        return null;
    }
}
package com.qijie.demo.zqjhttpclient.controller;

import com.qijie.demo.zqjhttpclient.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@EnableAsync
@RequestMapping(value = "/test")
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping(value = "/testAsyncVoidReturnType")
    public void testAsyncAnnotationForMethodsNoReturnType(){
        testService.asyncMethodWithVoidReturnType();
    }

    @GetMapping(value = "/testAsyncWithReturnType")
    public void testAsyncAnnotationForMethodsWithReturnType()
            throws InterruptedException, ExecutionException {
        Future<String> future = testService.asyncMethodWithReturnType();//Future接口接收异步方法的返回值
        System.out.println(future.get());//打印返回值
    }
}

启动项目,在浏览器http://localhost:8080/test/testAsyncVoidReturnType执行结果:

5.基于@Async返回值的调用

在上面代码中可以发现,返回的数据类型为Future类型,其为一个接口。具体的结果类型为AsyncResult,这个是需要注意的地方。在controller方法中调用有返回值的异步方法。启动项目,在浏览器http://localhost:8080/test/testAsyncWithReturnType执行结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值