2017-02-28 58 views
8

我是新的Java 8并发特性,如CompletableFuture,我希望你能帮助上手以下使用情况。的Java 8 - 呼叫方法异步并行,并结合他们的结果

有一个名为TimeConsumingServices服务,提供耗时的操作,我想以并行方式运行,因为它们都是独立于。

interface TimeConsumingService { 

    default String hello(String name) { 
    System.out.println(System.currentTimeMillis() + " > hello " + name); 
    return "Hello " + name; 
    } 
    default String planet(String name) { 
    System.out.println(System.currentTimeMillis() + " > planet " + name); 
    return "Planet: " + name; 
    } 
    default String echo(String name) { 
    System.out.println(System.currentTimeMillis() + " > echo " + name); 
    return name; 
    } 

    default byte[] convert(String hello, String planet, String echo) { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(hello); 
    sb.append(planet); 
    sb.append(echo); 
    return sb.toString().getBytes(); 
    } 
} 

到目前为止,我实现了以下示例,并且我设法并行调用了所有三种服务方法。

public class Runner implements TimeConsumingService { 

    public static void main(String[] args) { 
    new Runner().doStuffAsync(); 
    } 

    public void doStuffAsync() { 
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> this.hello("Friend")); 
    CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> this.planet("Earth")); 
    CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> this.echo("Where is my echo?")); 

    CompletableFuture.allOf(future1, future2, future3).join(); 
    } 
} 

有没有办法收集每个服务调用的返回值和调用方法byte[]‘ convert(String, String, String)

回答

8

要合并的结果你已经返回他们毕竟,你可以做这样的事情

CompletableFuture<byte[]> byteFuture = CompletableFuture.allOf(cf1, cf2, cf3) 
        .thenApplyAsync(aVoid -> convert(cf1.join(), cf2.join(), cf3.join())); 
byte[] bytes = byteFuture.join(); 

这将运行所有的期货,等待他们都只要他们都完成了将打电话给你的完成,然后你提到的方法。

2

后加入,你可以简单地从future1get()值:

String s1 = future1.get() 

+0

但如果我叫'future1.get(); future2.get(); future3.get();'它们不是并行调用的,不是吗? – saw303

+2

当你调用future1.get(),那么你只得到已经计算的结果。 –

+1

是取得成果是不是在并行调用,但是所有的方法将被异步计算。你可以通过添加'TimeUnit.seconds(2).sleep()'来检查它。加入方法后。你会看到'System.out.println'在睡眠之前被调用。 – user2377971

0

您可以使用这些方法thenCombine()如果只有3期货完成合并:

final CompletableFuture<byte[]> byteFuture = future1.thenCombine(future2, (t, u) -> { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(t); 
    sb.append(u); 
    return sb.toString(); 
}).thenCombine(future3, (t, u) -> { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(t); 
    sb.append(u); 
    return sb.toString(); 
}).thenApply(s -> s.getBytes()); 

try { 
    final byte[] get = byteFuture.get(); 
} catch (InterruptedException | ExecutionException ex) { 
}