gpt4 book ai didi

Java 8 并行运行多个方法

转载 作者:行者123 更新时间:2023-11-29 08:31:49 24 4
gpt4 key购买 nike

我有 2 个方法,它们具有不同的返回类型,我想同时运行它们。这是我的代码:

public void method(int id) {
final CompletableFuture<List<FooA>> fooACF = CompletableFuture.supplyAsync(() -> generateFooA(id));
final CompletableFuture<List<FooB>> fooBCF = CompletableFuture.supplyAsync(() -> generateFooB(id));
List<FooA> fooAs = fooACF.get();
List<FooB> fooBs = fooBCF.get();
//Do more processesing
}

public List<FooA> generateFooA(int id) {
//code
}

public List<FooB> generateFooB(int id) {
//code
}

但我不知道这两种方法是否会与上述代码并行运行,或者我是否最好说:

List<FooA> fooAs = generateFooA(id);
List<FooB> fooBs = generateFooB(id);

如何正确使用可完成的 future 才能并行运行这两种方法?

最佳答案

使用 ForkJoinPool.commonPool() 提供的线程,您的代码工作正常,正如 JavaDoc 为 CompletableFuture.supplyAsync(Supplier<U> supplier) 所 promise 的那样.您可以通过添加一些 sleep() 以快速而肮脏的方式证明它和 println()声明。我使用 String 稍微简化了您的代码而不是 List<Foo> :

public void method(int id) throws InterruptedException, ExecutionException {
CompletableFuture<String> cfa = CompletableFuture.supplyAsync(() -> generateA(id));
CompletableFuture<String> cfb = CompletableFuture.supplyAsync(() -> generateB(id));
String fooA = cfa.get();
String fooB = cfb.get();
System.out.println("Final fooA " + fooA);
System.out.println("Final fooB " + fooB);
}

public String generateA(int id) {
System.out.println("Entering generateA " + Thread.currentThread());
sleep(2000);
System.out.println("Leaving generateA");
return "A" + id;
}

public String generateB(int id) {
System.out.println("Entering generateB " + Thread.currentThread());
sleep(1000);
System.out.println("Leaving generateB");
return "B" + id;
}

private void sleep(int n) {
try {
Thread.sleep(n);
} catch (InterruptedException ex) {
// never mind
}
}

输出是:

Entering generateFooA Thread[ForkJoinPool.commonPool-worker-1,5,main]
Entering generateFooB Thread[ForkJoinPool.commonPool-worker-2,5,main]
Leaving generateFooB
Leaving generateFooA
Final fooA A1
Final fooB B1

可以手动观察1秒2秒后出现“Leaving”输出行。如需更多证据,您可以在输出中添加时间戳。如果您更改 sleep 的相对长度,您会看到“离开”输出以不同的顺序出现。


如果省略 sleep() s,那么很可能第一个线程完成得如此之快以至于它在第二个线程开始之前就完成了:

Entering generateA Thread[ForkJoinPool.commonPool-worker-1,5,main]
Leaving generateA
Entering generateB Thread[ForkJoinPool.commonPool-worker-1,5,main]
Leaving generateB
Final fooA A1
Final fooB B1

请注意,这一切发生得如此之快,以至于在运行时请求第二个线程时线程已返回到池中。所以原来的线程被复用了。

这也可能发生在非常短的 sleep 时,尽管在我的系统上每次运行时 1 毫秒的 sleep 就足够了。当然是 sleep()是需要时间才能完成的“真实”操作的占位符。如果您的实际操作非常便宜,以至于它在另一个线程开始之前就完成了,那么这是一个很好的暗示,表明在这种情况下多线程是无益的。


但是如果你需要问如何证明事情是同时发生的,我想知道你为什么要让它们同时发生。如果您的程序在并发或顺序执行这些任务时没有“现实世界”可观察到的差异,那么为什么不让它顺序运行呢?更容易推理顺序操作;有很多与并发相关的偷偷摸摸的错误。

也许您希望通过多线程来提高速度——如果是这样的话,速度的提高应该是您要测量的,而不是事情是否实际上是并发的。请记住,对于大量任务,CPU 并行执行它们的速度无法比顺序执行更快。

关于Java 8 并行运行多个方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47401536/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com