使用SpringBoot的@Async实现异步调用方法,以及自己开启新线程异步调用
2023-06-13 09:12:32 时间
大家好,又见面了,我是你们的朋友全栈君。
一. springboot的@Async注解实现异步
要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async
就可以了
1.准备工作
准备一个springboot工程,在Application类上加上EnableAsync
注解开启异步
/** * @Author: zgd * @Date: 18/09/12 10:27 * @Description: */
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
这个注解如果不加,@Async注解失效
2.controller
写一个同步接口和异步接口
package com.zgd.demo.thread.asyn.controller;
import com.zgd.demo.thread.asyn.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
/** * @Author: zgd * @Date: 18/09/12 10:26 * @Description: hello */
@RestController
@RequestMapping("/hello")
public class HelloController {
@Autowired
private HelloService helloService;
/** * 异步方法 * @return */
@RequestMapping("/asyn")
public String getAsynHello(){
long n = Instant.now().toEpochMilli();
//异步
String s = helloService.asynchSayHello();
long f = Instant.now().toEpochMilli();
return s + " 时间: " + (f-n);
}
/** * 同步方法 * * @return */
@RequestMapping("/sync")
public String getSyncHello(){
long n = Instant.now().toEpochMilli();
//异步
String s = helloService.synchSayHello();
long f = Instant.now().toEpochMilli();
return s + " 时间: " + (f-n);
}
}
3.helloService
写一个HelloService接口,并实现该接口
package com.zgd.demo.thread.asyn.service.impl;
import com.zgd.demo.thread.asyn.service.HelloService;
import com.zgd.demo.thread.asyn.service.SleepService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/** * @Author: zgd * @Date: 18/09/12 10:43 * @Description: */
@Service
public class HelloServiceImpl implements HelloService {
@Autowired
private SleepService sleepService;
@Override
public String synchSayHello() {
try {
sleepService.syncSleep();
return "hello world,这是同步方法";
} catch (InterruptedException e) {
e.printStackTrace();
return "error";
}
}
@Override
public String asynchSayHello() {
try {
System.out.println("主线程 "+Thread.currentThread().getName());
sleepService.asyncSleep();
return "hello world,这是异步方法";
} catch (InterruptedException e) {
e.printStackTrace();
return "error";
}
}
}
这里为了模拟应用场景,将耗时的方法放在另一个service里面,就叫SleepService,同样的,实现这个接口
package com.zgd.demo.thread.asyn.service.impl;
import com.zgd.demo.thread.asyn.service.SleepService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/** * @Author: zgd * @Date: 18/09/12 10:46 * @Description: */
@Service
public class SleepServiceImpl implements SleepService {
@Override
public void syncSleep() throws InterruptedException {
System.out.println("线程名: " +Thread.currentThread().getName());
System.out.println("开始同步休眠3秒");
Thread.sleep(3000);
System.out.println("同步休眠结束");
}
@Override
@Async
public void asyncSleep() throws InterruptedException {
System.out.println("次线程 "+Thread.currentThread().getName());
System.out.println("开始异步休眠3秒");
Thread.sleep(3000);
System.out.println("异步休眠休眠结束");
}
}
两个方法都是休眠3秒,aysncSleep方法上面有一个@Async
注解
4.测试
- 同步 访问 http://localhost:8080/hello/sync
控制台
要3秒的时间才能收到响应
- 异步 访问 http://localhost:8080/hello/asyn
可见主线程和次线程打印出来的线程名不一样,也就是springboot帮我们开启了一个线程去处理
注意事项
- 必须要加
@EnableAsync
注解 - 不能在同一类下调用@Async注解的方法,比如A类下有a和b方法,b方法有@Async注解,不能直接这样a调用b,要把b放到其他类中
- @Async也可以打在类上,这样类下面的所有方法都是异步的(被其他类调用的时候)
二.开启线程实现异步
如果我们没有使用springboot,使用传统的方法怎么异步调用方法?还是开启一个新的线程
1.controller
增加一个接口
/** * 同步方法 * * @return */
@RequestMapping("/thread/asyn")
public String getThreadSyncHello(){
long n = Instant.now().toEpochMilli();
//异步
String s = helloService.threadAsynchSayHello();
long f = Instant.now().toEpochMilli();
return s + " 时间: " + (f-n);
}
2.service
HelloServiceImpl
@Override
public String threadAsynchSayHello() {
//还是休眠3秒
Runnable runnable = ()-> {
try {
sleepService.syncSleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
System.out.println(Thread.currentThread().getName()+" 开启新线程");
new Thread(runnable).start();
return "hello world,这是开启线程的异步方法";
}
3.测试
我们访问 http://localhost:8080/hello/thread/asyn
同样的两个线程名不一样,开启了一个新线程处理,并且多次测试可以看出,自己直接开启线程比@Async要快几毫秒,不过可以忽略不计了
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/157522.html原文链接:https://javaforall.cn
相关文章
- springboot-mybatis多数据源的两种整合方法[通俗易懂]
- springboot集成mybatisplus分页_mybatis分页查询原理
- springboot启动监听线程_Springboot启动流程
- SpringBoot日志源码解析:日志监听器的注册方法及触发
- SpringBoot打包:Failed to execute goal org.apache.maven.plugins
- springboot使用h2数据库做单元测试_h2数据库对接SQL
- SpringBoot之引导类[Application]
- springboot文件上传方法详解
- 别再用main方法测试了,太Low!这才是专业的SpringBoot项目测试方法!
- 【开发经验】SpringBoot与Vue-cli解决前后端交互跨域问题
- SpringBoot自动装配原理分析,手写starter组件
- 详解SpringBoot 整合mongoDB并自定义连接池的方法代码
- 一步步教你SpringBoot整合MongoDB的实现步骤
- SpringBoot 开启Redis缓存及使用方法
- 使用SpringBoot集成redis的方法
- springboot-security02FromDB 权限管理(用户信息和角色信息保存在数据库)详解程序员
- SpringBoot开发案例从0到1构建分布式秒杀系统详解架构师
- springboot 使用c3p0数据库连接池的方法详解编程语言
- springboot发布和监听事件详解编程语言
- Springboot热部署-devtools详解编程语言