一尘不染

@Async阻止线程继续执行,直到其他线程完成

java

我有一个应用程序,在某些情况下需要计算某些次数。此计算功能具有@Async注释(来自Spring
Framework),可以在4个线程上运行这些计算。问题是我需要大约40000个这些计算,并且我想知道所有计算的开始和结束之间的时间,因此我看到在调用计算函数的for循环之前和之后的时间是什么。但是现在所有计算都放入队列中,因此for循环立即完成,时间大约为1秒,而计算要花几个小时才能完成。我尝试将最大队列大小设置为大约100(这也有助于减少内存使用),但这也不是解决方案,因为我将错过总花费的最后100次计算。

这是一些代码,它说明了相同的问题:

执行类:

public class Foo {
    public void executeBlaALotOfTimes() {
        long before = System.currentTimeMillis();

        for (int i = 0; i<40000; i++) {
            executeBla();
        }

        long after = System.currentTimeMillis();

        System.out.println("Time it took for a lot of bla to execute: " + (after - before) / 1000.0 + " seconds.");
    }
}

以及执行计算的类:

@Service
public class Bar {
    @Async
    public void executeBla() {
        System.out.println("Bla!");
    }
}

这将导致以下输出(假设Foo中的代码无限快速地执行):

bla执行大量时间:0.0秒。
布拉!
布拉!
布拉!
布拉!
。
。
。
等等

阅读 505

收藏
2020-12-03

共1个答案

一尘不染

如果您需要等待执行完成,则可以返回a Future作为返回值,例如

@Async
public Future<Void> executeBla() {
    System.out.println("Bla!");
    return new AsyncResult<Void>(null);
}

这是人为的,因为没有返回实际值,但是它仍然允许调用代码等待所有执行完成:

public void executeBlaALotOfTimes() {
    long before = System.currentTimeMillis();

    Collection<Future<Void>> futures = new ArrayList<Future<Void>>();

    for (int i = 0; i<40000; i++) {
        futures.add(executeBla());
    }

    for (Future<Void> future : futures) {
        future.get();
    }

    long after = System.currentTimeMillis();

    System.out.println("Time it took for a lot of bla to execute: " + (after - before) / 1000.0 + " seconds.");
}

在这里,第一个循环触发异步任务并将期货存储在列表中。然后秒循环遍历期货,等待每一个期货结束。

2020-12-03