@Async+Future返回值

使用@Async方法有void和Future两种返回值
其中void前面demo中已经写过,本篇文档主要写Future。

借用举例

AsyncResult是异步方式,异步主要用于调用的代码需要长时间运行,才能返回结果的时候,可以不阻塞调用者。

打个比方,同步方式就是你打电话给客服,客服没法立刻解决,客服说你等等,别挂电话,然后等了10分钟,再告诉你。再挂电话。
此时电话费照收,并且你不能接打别人的电话。

异步方式就是,客服说,我先查查,查到了给你回电话,然后挂断。你干别的事情。等了10分钟,客服给你来电话了,告诉你结果。

使用经验

使用@Async的返回,代码中通常new AsyncResult<返回类型>(返回值),方法中返回类型的Future。AsyncResult类实现了ListenableFuture接口,ListenableFuture实现了Future接口

Future常用方法

在这里插入图片描述
isDone() 返回Boolean类型值,用来判断该异步任务是否执行完成,如果执行完成,则返回true,如果未执行完成,则返回false.

cancel(boolean mayInterruptRunning) 返回boolean类型值,参数也是一个boolean类型的值,用来传入是否可以打断当前正在执行的任务。如果参数是true且当前任务没有执行完成 ,说明可以打断当前任务,那么就会返回true,如果当前任务还没有执行,那么不管参数是true还是false,返回值都是true,如果当前任务已经完成,那么不管参数是true还是false,那么返回值都是false,如果当前任务没有完成且参数是false,那么返回值也是false。总结下来就是:1.如果任务还没执行,那么如果想取消任务,就一定返回true,与参数无关。2.如果任务已经执行完成,那么任务一定是不能取消的,所以此时返回值都是false,与参数无关。3.如果任务正在执行中,那么此时是否取消任务就看参数是否允许打断(true/false)。

isCancelled() 返回的是boolean类型,如果是上面总结的第三种情况,这才是真正意义上有机会被取消的任务,那么此时如果上面的方法返回的是true,那么说明任务取消成功了,则这个方法返回的也就是true。

get() 返回的是在异步方法中最后return 的那个对象中的value的值。主要是通过里面的get()方法来获取异步任务的执行结果,这个方法是阻塞的,直到异步任务执行完成。

get(long timeout,TimeUnit unit) 这个方法和get()的功能是一样的(在方法执行没有超时的情况下效果是一样的),只不过这里参数中设置了超时时间,因为get()在执行的时候是需要等待回调结果的,是阻塞在那里的,如果不设置超时时间,它就阻塞在那里直到有了任务执行完成。我们设置超时时间,就可以在当前任务执行太久的情况下中断当前任务,释放线程,这样就不会导致一直占用资源。参数一是时间的数值,参数二是参数一的单位,可以在TimeUnit这个枚举中选择单位。如果任务执行超时,则抛出TimeOut异常,返回的message就是null。

demo代码

Future < String>

controller

package com.example.worktest.async.async_future.controller;


import com.example.worktest.async.async_future.service.FutureService;
import org.springframework.beans.factory.annotation.Autowired;
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
@RequestMapping("/v3")
public class FutureController {
    @Autowired
    private FutureService futureService;

    @RequestMapping("/test")
    public String isDoneTest() throws InterruptedException, ExecutionException {
        System.out.println("开始访问");
        long l1 = System.currentTimeMillis();
        Future<String> r1 = futureService.JobOne();
        Future<String> r2 = futureService.JobTwo();
        Future<String> r3 = futureService.JobThree();
        while(true) {//死循环,每隔2000ms执行一次,判断一下这三个异步调用的方法是否全都执行完了。
            if(r1.isDone() && r2.isDone() && r3.isDone()) {//使用Future的isDone()方法返回该方法是否执行完成
                //如果异步方法全部执行完,跳出循环
                break;
            }
            Thread.sleep(2000);//每隔2000毫秒判断一次
        }
        long l2 = System.currentTimeMillis();//跳出while循环时说明此时三个异步调用的方法都执行完成了,此时得到当前时间

        String result = r1.get();
        System.out.println("结束访问,用时"+(l2-l1));
        System.out.println("使用get方法获得的返回内容:"+result);
        return "finished";
    }

}

service:

package com.example.worktest.async.async_future.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Service
public class FutureService {
    @Async
    public Future<String> JobOne() throws InterruptedException {
        System.out.println("开始执行任务一");
        long l1 = System.currentTimeMillis();
        Thread.sleep(2000);
        long l2 = System.currentTimeMillis();
        System.out.println("任务一_用时"+(l2-l1));
        return new AsyncResult<String>("任务一完成");//可以使用try,catch定义在正常完成时返回一个success信息,出现异常时返回error信息。
    }

    @Async
    public Future<String> JobTwo() throws InterruptedException {
        System.out.println("开始执行任务二");
        long l1 = System.currentTimeMillis();
        Thread.sleep(2000);
        long l2 = System.currentTimeMillis();
        System.out.println("任务二_用时"+(l2-l1));
        return new AsyncResult<String>("任务二完成");
    }


    @Async
    public Future<String> JobThree() throws InterruptedException {
        System.out.println("开始执行任务三");
        long l1 = System.currentTimeMillis();
        Thread.sleep(2000);
        long l2 = System.currentTimeMillis();
        System.out.println("任务三_用时"+(l2-l1));
        return new AsyncResult<String>("任务三完成");
    }


}

在这里插入图片描述

Future< List< xxx> >

@Override
  @Async
  public Future<List<ResBaseProductShopVO>> searchShopProductAsync(ReqBaseProductShopPageEsQueryVO query) {
    List<ResBaseProductShopVO> res = new ArrayList<>(5000);
    if (query != null) {
      while (true) {
        List<ResBaseProductShopVO> vos = esService.baseProductShopEsTermsSearch(query);
        if (CollectionUtils.isNotEmpty(vos)) {
          res.addAll(vos);
          if (!query.continueSearch(vos.size())) {
            break;
          }
          query.increase();
        } else {
          break;
        }
      }
    }
    return new AsyncResult<>(res);

Future返回结果


 @Override
    public void obtainFromFuture(List<Future<List<ResBaseProductShopVO>>> futures, List<ResBaseProductShopVO> result) throws ExecutionException, InterruptedException {
        Iterator<Future<List<ResBaseProductShopVO>>> iterator = futures.iterator();
        while (iterator.hasNext()) {
            Future<List<ResBaseProductShopVO>> future = iterator.next();
            if (future.isDone()) {
                List<ResBaseProductShopVO> source = future.get();
                if (CollectionUtils.isNotEmpty(source)) {
                    result.addAll(source);
                }
                iterator.remove();
            }
            if (!iterator.hasNext()) {
                iterator = futures.iterator();
            }
        }
    }
  • 16
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值