java - @Async 阻止线程继续,直到其他线程完成

标签 java multithreading spring asynchronous queue

我有一个应用程序需要计算一定次数的东西。此计算函数具有注释 @Async(来自 Spring 框架),这使得可以在 4 个线程上运行这些计算。问题是我需要大约 40000 个这样的计算,我想知道所有计算的开始和结束之间的时间,所以我看到调用计算函数的 for 循环之前和之后的时间。但是现在所有的计算都放在一个队列中,所以 for 循环立即结束,时间大约是 1 秒,而计算需要几个小时才能完成。我尝试将最大队列大小设置为大约 100(也有助于减少内存使用)但这也不是解决方案,因为我会错过总时间的最后 100 次计算。有没有办法在 for 循环之后暂停执行代码,直到所有线程完成工作,但仍然能够使用 @Async 注释?

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

执行类:

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 中的代码执行得无限快):

Time it took for a lot of bla to execute: 0.0 seconds.
Bla!
Bla!
Bla!
Bla!
.
.
.
etc

最佳答案

如果您需要等待执行完成,那么您可以返回一个 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.");
}

在这里,第一个循环触发异步任务并将 future 存储在列表中。秒循环然后迭代 future ,等待每个完成。

关于java - @Async 阻止线程继续,直到其他线程完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4324212/

相关文章:

java - 通过 ID 检索数组的名称

spring - 如何将文件的内容作为值传递给 Spring 属性?

java - 如何在 Android 中的数组列表中执行 getter 和 setter

Java输入流追加而不删除

python - 如何使用 threading 模块暂停和恢复线程?

python - 在 Python 2 中线程化一个无休止的 while 循环

java - Spring JtaTransactionManager 是否会自动省略两阶段提交中每个事务未使用的资源?

c# - Spring.NET 等效于 Java Spring 数据访问用法

java - 使用 JAX-WS 绑定(bind)自定义重命名具有相同名称的 WSDL 元素

java - 当变量值改变时如何更新JTextField?