反应式编程在管理异步操作的线程方面是否更节省内存?

问题描述 投票:0回答:1

我在测试中经常使用

Awaitility
来处理异步操作。但是,每个
Awaitility
调用都会生成线程,这会导致运行大型测试时内存消耗较高。我正在寻找一种替代解决方案,它提供类似的功能,但内存效率更高。


示例场景:

下面是一个简化的示例,我需要在

0
10,000,000
之间找到 500 个随机素数。

使用等待:

static void waitWithAwaitility() {
    AtomicInteger primeCount = new AtomicInteger(0);
    await()
        .atMost(1, TimeUnit.HOURS)
        .pollInterval(3, TimeUnit.SECONDS)
        .until(() -> {
            int number = supplierMethod().get();
            if (isPrime(number)) {
                System.out.println("Found prime: " + number);
                primeCount.incrementAndGet();
            }
            return primeCount.get() >= 500;
        });
}

辅助方法:

public static Supplier<Integer> supplierMethod() {
    int number = new Random().nextInt(10_000_000) + 1;
    System.out.println("Generated number: " + number);
    return () -> number;
}

public static boolean isPrime(int number) {
    if (number <= 1) return false;
    for (int i = 2; i <= Math.sqrt(number); i++) {
        if (number % i == 0) return false;
    }
    return true;
}

当我使用 VisualVM 等工具分析内存使用情况时,我注意到内存占用量很大。 enter image description here


探索替代方案:

ChatGPT 建议使用反应式编程(使用 Project Reactor)作为替代方案。我尝试实施以下解决方案:

反应式编程示例:

public Mono<Integer> reactiveAwait(
    Supplier<Integer> supplierMethod,
    Predicate<Integer> condition,
    Duration pollInterval,
    Duration timeout
) {
    return Mono.defer(() -> Mono.fromSupplier(supplierMethod))
        .repeatWhen(repeat -> repeat.delayElements(pollInterval))
        .takeUntil(condition::test)
        .last()
        .timeout(timeout, Mono.error(new RuntimeException("Timeout exceeded")))
        .onErrorResume(throwable -> {
            System.err.println(throwable.getMessage());
            return Mono.empty();
        })
        .subscribeOn(Schedulers.boundedElastic());
}

static void waitWithJavaRx() {
    AtomicInteger primeCount = new AtomicInteger(0);

    Mono<Integer> result = new DifferentAwaitility().reactiveAwait(
        () -> supplierMethod().get(),
        number -> {
            boolean primeStatus = isPrime(number);
            System.out.println("Is prime? " + primeStatus);
            if (primeStatus) {
                primeCount.incrementAndGet();
            }
            return primeCount.get() >= 500;
        },
        Duration.ofSeconds(3),
        Duration.ofHours(1)
    );

    Integer finalResult = result.block();
    if (finalResult != null) {
        System.out.println("Result: " + finalResult);
    } else {
        System.err.println("Error: Timeout or other failure occurred");
    }
}

反应式方法的问题:
虽然这种方法有效,但内存消耗比使用

Awaitility
时高出三倍。以下是比较内存使用情况的 VisualVM 屏幕截图:

enter image description here


问题:
是否有更好的方法来实现与

Awaitility
类似的功能,但内存消耗更低?我探索过响应式编程,但它对减少内存使用没有帮助。任何建议或优化将不胜感激!

java multithreading memory-management reactive-programming
1个回答
0
投票

您是否尝试过按照 Awaitlity 文档中所述使用 ExecutorService?

https://github.com/awaitility/awaitility/wiki/Usage#thread-handling

至于反应式和更高的内存占用,我的猜测是它可能运行得更快,从而更快地分配对象,但这只是一个大脑放屁。

© www.soinside.com 2019 - 2024. All rights reserved.