springboot的@Async,如何控制执行顺序?

假设我有三个方法想要异步,在一个类中,有如下调用

Utils.insertUser();

Utils.insertAddress();

Utils.insertInformation();

Utils.selectAll()

首先,前三个方法是设置了@Async的注解方法,假设他是往数据库里面插入数据,第四个是把插入的数据查出来,数据来源就是前三个方法,这个方法没有@Async注解。

现在的问题是,由于前三个方法设置了@Async,导致前三个方法可能还未执行完毕,第四个查询方法就已经开始执行了,这样就没有意义了。所以,如何做到保证前三个方法异步执行,且全部执行完毕后,再执行第四个方法?

其实你可以不用 @Asyn,只是想要这三个操作并发执行而已

  public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newCachedThreadPool();
    CountDownLatch latch = new CountDownLatch(3);

    executorService.execute(() -> {
      try {
        TimeUnit.SECONDS.sleep(1);
        System.out.println("执行第一个操作");
      } catch (InterruptedException e) {
      } finally {
        latch.countDown();
      }
    });

    executorService.execute(() -> {
      try {
        TimeUnit.SECONDS.sleep(2);
        System.out.println("执行第二个操作");
      } catch (InterruptedException e) {
      } finally {
        latch.countDown();
      }
    });

    executorService.execute(() -> {
      try {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("执行第三个操作");
      } catch (InterruptedException e) {
      } finally {
        latch.countDown();
      }
    });
    
    // 等待前三个执行完毕
    latch.await();

    System.out.println("执行第四个操作");
    executorService.shutdown();
  }

三个异步方法返回 CompletableFuture 

使用CompletableFuture.allOf 等待三个异步方法都执行完毕

再调用第4个方法

可以在异步任务完成后写一个状态,这个状态可以写到像Redis这样的内存数据库中。

由最后的Utils.selectAll()检测完成状态后继续执行。

1验证+阻塞  2自旋查询有结果就返回   3利用CountDownLatch  你要的不是顺序执行 要的是前置条件先完成

直接用注解好像不行,写了个demo

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Utils.class, ExecutorConfiguration.class})
public class Test {

    @Autowired
    Utils utils;

    @org.junit.Test
    public void test1() {

        final Future<?> future = utils.insertUser();
        final Future<?> future1 = utils.insertAddress();
        final Future<?> future2 = utils.insertInformation();

        while (true) {
            if (future.isDone() && future1.isDone() && future2.isDone()) {
                utils.selectAll();
                break;
            }
        }
    }

}

@TestComponent
class Utils {

    @Autowired
    ThreadPoolTaskExecutor executor;

    public static void selectAll() {
        System.out.println("=====selectAll===");
    }

    public Future<?> insertUser() {

        final Future<?> insertUser = executor.submit(() -> {
            System.out.println("======insertUser======");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        return insertUser;

    }

    public Future<?> insertAddress() {
        final Future<?> insertUser = executor.submit(() -> {
            System.out.println("======insertAddress======");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        return insertUser;
    }

    public Future<?> insertInformation() {
        final Future<?> insertUser = executor.submit(() -> {
            System.out.println("======insertInformation======");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        return insertUser;
    }

}

@TestConfiguration
@EnableAsync
class ExecutorConfiguration {

    @Bean
    public ThreadPoolTaskExecutor asyncZipPictureThreadPool() {
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setCorePoolSize(10);
        return pool;

    }

}

 

您好,我是有问必答小助手,你的问题已经有小伙伴为您解答了问题,您看下是否解决了您的问题,可以追评进行沟通哦~

如果有您比较满意的答案 / 帮您提供解决思路的答案,可以点击【采纳】按钮,给回答的小伙伴一些鼓励哦~~

ps:问答VIP仅需29元,即可享受5次/月 有问必答服务,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632