首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8并行运行多个方法

Java 8并行运行多个方法
EN

Stack Overflow用户
提问于 2017-11-21 05:38:41
回答 3查看 16.7K关注 0票数 3

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

代码语言:javascript
复制
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
}

但我不知道这两种方法是否会与上面的代码并行运行,或者我只是更好地说:

代码语言:javascript
复制
List<FooA> fooAs = generateFooA(id);
List<FooB> fooBs = generateFooB(id);

我如何正确地使用可完成的未来,以便能够并行运行这两种方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-22 00:43:03

正如CompletableFuture.supplyAsync(Supplier<U> supplier)的JavaDoc所承诺的那样,使用ForkJoinPool.commonPool()提供的线程,您的代码工作得很好。您可以通过添加一些sleep()println()语句来快速证明这一点。我使用String而不是List<Foo>简化了您的代码

代码语言:javascript
复制
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
    }
}

输出为:

代码语言:javascript
复制
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秒后出现“离开”输出行。要获得更多证据,可以在输出中添加时间戳。如果更改休眠的相对长度,您将看到“离开”输出以不同的顺序出现。

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

代码语言:javascript
复制
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

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

虽然在我的系统上,每次我运行它时,1ms的睡眠时间就足够了,但这种情况也可能发生在非常短的睡眠时间内。当然,sleep()是一个需要时间才能完成的“真实”操作的占位符。如果您的实际操作非常廉价,以至于它在其他线程启动之前完成,这是一个很好的提示,表明这是一种多线程没有好处的场景。

然而如果你需要问如何证明事情是并发发生的,我想知道为什么你一开始就想让它们并发发生。如果在并发或顺序执行这些任务时,程序之间没有“真实世界”可观察到的差异,那么为什么不让它按顺序运行呢?更容易理解顺序操作;有很多与并发相关的隐蔽的bug。

也许您希望通过多线程来提高速度--如果是这样的话,速度的提高应该是您所测量的,而不是事情是否真正并发。请记住,对于非常多的任务,CPU不可能以并行方式比顺序执行得更快。

票数 14
EN

Stack Overflow用户

发布于 2017-11-21 05:55:02

正如我在我的评论中所说的,检查How to start two threads at "exactly" the same time,但这应该是你想要的

代码语言:javascript
复制
final CyclicBarrier gate = new CyclicBarrier(3);
public void method(int id) {
    Thread one = new Thread (()->{
        gate.await();
        List<FooA> fooAs = generateFooA(id);
    });
    Thread two = new Thread (()->{
        gate.await();
        List<FooB> fooBs = generateFooB(id);
    });
    one.start();
    two.start();
    gate.await();
    //Do more processesing
}

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

public List<FooB> generateFooB(int id) {
    //code
}
票数 -1
EN

Stack Overflow用户

发布于 2017-11-21 06:14:37

你丢失了一个Executor

代码语言:javascript
复制
ExecutorService executor = Executors.newCachedThreadPool();
List<Future<?>> = Stream.<Runnable>of(() -> generateFooA(id), () -> generateFooA(id))
        .map(executor::submit)
        .collect(Collectors.toList());
for (Future<?> future : futures) {
    future.get(); // do whatever you need here
}

当您对它们执行submit时,Runnables就会开始执行。get()会尽快返回。例如,如果你的第一个get()是最慢的,所有其他的get()调用都会立即返回。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47401536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档