在
Java
应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在
spring
3.x之后,就已经内置了@Async来完美解决这个问题。
1.@Async介绍
在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
如何在Spring Boot中启用@Async。基于Java配置的启用方式:
@SpringBootApplication
@EnableAsync
public class Application{
public static ConfigurableApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(Application.class, args);
2. 基于@Async无返回值调用
使用的方式非常简单,一个标注即可解决所有的问题:
@Async //标注使用
public void asyncMethodWithVoidReturnType() {
System.out.println("Execute method asynchronously. "
+ Thread.currentThread().getName());
3. 基于@Async返回值的调用
返回的数据类型为Future类型,其为一个接口。具体的结果类型为AsyncResult,这个是需要注意的地方。
@Async
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;
调用返回结果的异步方法示例
public void testAsyncAnnotationForMethodsWithReturnType()
throws InterruptedException, ExecutionException {
System.out.println("Invoking an asynchronous method. " + Thread.currentThread().getName());
Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType();
while (true) { ///这里使用了循环判断,等待获取结果信息
if (future.isDone()) { //注意这里需要判断是否执行完毕, 否则future.get()获取结果可能会抛出空指针异常
System.out.println("Result from asynchronous process - " + future.get());
break;
System.out.println("Continue doing something else. ");
Thread.sleep(1000);
这些获取异步方法的结果信息,是通过不停的检查Future的状态来获取当前的异步方法是否执行完毕来实现的。
4.@Transaction,@Async在同一个类中注解失效的原因,参考https://blog.csdn.net/qq602757739/article/details/81327990
伪代码示例:
@Async
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, timeout = 36000, rollbackFor = Exception.class)
public Future<Integer> closeOrderAsync(long mId, BigInteger oId) {
private void a() {
//do insert
private void b() {
//do update
Feign接口的Request 默认是主线程和子线程不共享的,当异步调用Feign接口会因为获取不到ServletRequestAttributes报空指针。我们先获取到当前请求,再分享给子线程。首先获取attributes。
在jdk5中,我们通过使用Future和Callable,可以在任务执行完毕后得到任务执行结果。可以使用isDone检测计算是否完成,使用cancle停止执行任务,使用阻塞方法get阻塞住调用线程来获取返回结果,使用阻塞方式获取执行结果,有违异步编程的初衷,而且Future的异常只能自己内部处理。
jdk8中加入了实现类CompletableFuture<T>,用于异步编程。底层做任务使用的是ForkJoin, 顾名思义,是将任务的数据集分为多个子数据集,而每个子集,都可以由独立的子任
CompletableFuture优化接口性能案例需求背景解决方案
在教育中心所有课程详情页都大致包含下面这么些,每种卡片的数据可能来自不同的数据源。数据源可能就是缓存数据,也可能是第三方的接口返回数据。因此对于这个接口一次性返回这么多卡片信息还是有点重的,我们尽量要使得每个卡片请求的数据要够快。对于头部影藏卡片而言,在数据适配阶段串行调用了三个第三方接口,而且每个接口最大超时时间outTime=200~300ms,对整个接口的性能还是有很大影响。
课程详情头部隐藏卡片,课程详情头部促销卡片,
记录问题,暂时还没得到解决
最近在工作中遇到这个问题,自己找了很多资料,始终没得到解决,所以发出来看看是否有人跟我遇到同样的问题,一起讨论
关于这个Future接口有以下几个方法
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedE
callable多线程future.get()方法能获取到当前线程的执行结果,但是会阻塞当前线程,即当前线程执行结束获取到结果后才会继续执行下一个线程,解决方法:
创建一个List数组存储funture,在所有线程执行以后遍历list获取结果。
int count = 0;
List<Future<Integer>> res = new ArrayList<>();
ExecutorService executorService = Executors.newCached
2019-08-07 工作中遇到的问题
大概是: 有个线程池满了,然后新的任务使用CompletableFuture.supplyAsync执行,用future1.get(1, TimeUnit.SECONDS)) 去获取的时候报错java.util.concurrent.TimeoutException
报错java.util.concurrent.TimeoutException觉得很奇怪;随...
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent....
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context...
* @throws CancellationException {@inheritDoc}
public V get() throws InterruptedException, ExecutionException {
int s = state;