springboot+async异步接口实现和调用详解编程语言

什么是异步调用?

异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。

如何实现异步调用?

多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式。

在非spring目项目中我们要实现异步调用的就是使用多线程方式,可以自己实现Runable接口或者集成Thread类,或者使用jdk1.5以上提供了的Executors线程池。

StrngBoot中则提供了很方便的方式执行异步调用。

 异步接口的使用场景

耗时比较长,任务比较多的接口。比方说,文件下载,大文件下载比较耗时,这个时候就可以使用异步接口。

示例

代码入下

maven依赖:

 

<parent>   
    <groupId>org.springframework.boot</groupId>   
    <artifactId>spring-boot-starter-parent</artifactId>   
    <version>1.5.3.RELEASE</version>   
</parent>   
<dependencies>   
    <dependency>   
        <groupId>org.springframework.boot</groupId>   
        <artifactId>spring-boot-starter-web</artifactId>   
    </dependency>   
</dependencies> 

 

 

 

启动类:[email protected]

@SpringBootApplication   
@EnableAsync   
public class Application{   
   
    public static void main(String[] args) {   
        SpringApplication.run(Application.class, args);   
    }   
} 

Controller 

[email protected]

 

@RestController   
@RequestMapping("")   
public class AsyncTaskController {   
       
    @RequestMapping("")   
    public String doTask() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        this.task1();   
        this.task2();   
        this.task3();   
        long currentTimeMillis1 = System.currentTimeMillis();   
        return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";   
    }   
       
    @Async   
    public void task1() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(1000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
    }   
       
    @Async   
    public void task2() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(2000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
    }   
    @Async   
    public void task3() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(3000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
    }   
} 

 

main函数运行spirngboot项目,启动完成后浏览器访问:

http://localhost:8080/

 

控制台:

 

task1任务耗时:1012ms   
 
task2任务耗时:2009ms   
 
task3任务耗时:3004ms  

 

等了一段浏览器时候输出入下:

task任务总耗时:6002ms   

 

异步并没有执行!

难道是代码写错了?反复检查了好几遍,并没有发现什么明显错误,[email protected][email protected],是生成一个代理类,由代理类去开启关闭事务,而在同一个类中,方法调用是在类体内执行的,spring无法截获这个方法调用。

豁然开朗,将异步任务单独放到一个类中,调整代码入下:

 

Controller

@RequestMapping("")   
@RestController   
public class AsyncTaskController {   
       
    @Autowired   
    private AsyncTask asyncTask;   
       
    @RequestMapping("")   
    public String doTask() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        asyncTask.task1();   
        asyncTask.task2();   
        asyncTask.task3();   
        long currentTimeMillis1 = System.currentTimeMillis();   
        return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";   
           
    }   
}  

 

异步任务类

@Component   
public class AsyncTask {   
       
    @Async   
    public void task1() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(1000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
    }   
       
    @Async   
    public void task2() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(2000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
    }   
    @Async   
    public void task3() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(3000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
    }   
}  

控制台:

task1任务耗时:1012ms   
 
task2任务耗时:2009ms   
 
task3任务耗时:3004ms  

访问浏览器结果入下:

 

task任务总耗时:19ms

 

异步调用成功!

 

如何知道三个异步任务什么时候执行完,执行的结果怎样呢?可以采用添加Fature回调方式判断

代码入下:

异步任务类

 

@Component   
public class AsyncTask {   
       
    @Async   
    public Future<String> task1() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(1000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
        return new AsyncResult<String>("task1执行完毕");   
    }   
       
    @Async   
    public Future<String> task2() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(2000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
        return new AsyncResult<String>("task2执行完毕");   
    }   
    @Async   
    public Future<String> task3() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Thread.sleep(3000);   
        long currentTimeMillis1 = System.currentTimeMillis();   
        System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");   
        return new AsyncResult<String>("task3执行完毕");   
    }   
}  

Controller

@RequestMapping("")   
@RestController   
public class AsyncTaskController {   
       
    @Autowired   
    private AsyncTask asyncTask;   
       
    @RequestMapping("")   
    public String doTask() throws InterruptedException{   
        long currentTimeMillis = System.currentTimeMillis();   
        Future<String> task1 = asyncTask.task1();   
        Future<String> task2 = asyncTask.task2();   
        Future<String> task3 = asyncTask.task3();   
        String result = null;   
        for (;;) {   
            if(task1.isDone() && task2.isDone() && task3.isDone()) {   
                // 三个任务都调用完成,退出循环等待   
                break;   
            }   
            Thread.sleep(1000);   
        }   
        long currentTimeMillis1 = System.currentTimeMillis();   
        result = "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";   
        return result;   
    }   
}  

控制台输出:

task1任务耗时:1000ms   
task2任务耗时:2001ms   
task3任务耗时:3001ms  

浏览器输出:

<span style="font-family:Simsun;font-size:14px;">task任务总耗时:4015ms</span>  

异步调用成功,并且在所有任务都完成时程序才返回了结果!

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/15688.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论