2016-04-02 17 views
2

私はCompleteableFuture操作を連鎖するための実証例を作成していると私は私が近いんだけど、私は欠けている何かがあると思います。すべてがmain()の最後の「並行して、ケーキを構築する」条項を除いてコンパイルされます。のJava 8 thenApply()とthenAccept()

import java.util.*; 
import java.util.concurrent.*; 
import java.util.function.*; 
import java.util.stream.*; 
import java.time.*; 

// Use decorator pattern to build up the cake: 

interface Cake_ { 
    String describe(); 
} 

class Cake implements Cake_ { 
    private int id; 
    public Cake(int id) { this.id = id; } 
    @Override 
    public String describe() { 
    return "Cake " + id; 
    } 
} 

abstract class Decorator implements Cake_ { 
    protected Cake_ cake; 
    public Decorator(Cake_ cake) { 
    this.cake = cake; 
    } 
    @Override 
    public String describe() { 
    return cake.describe(); 
    } 
    @Override 
    public String toString() { 
    return describe(); 
    } 
} 

class Frosted extends Decorator { 
    public Frosted(Cake_ cake) { 
    super(cake); 
    } 
    @Override 
    public String describe() { 
    return cake.describe() + " Frosted"; 
    } 
} 

class Decorated extends Decorator { 
    public Decorated(Cake_ cake) { 
    super(cake); 
    } 
    @Override 
    public String describe() { 
    return cake.describe() + " Decorated"; 
    } 
} 

// For the cake-building assembly line: 

class CreateCakes implements Supplier<Cake> { 
    private int id; 
    public CreateCakes(int id) { 
    this.id = id; 
    } 
    @Override 
    public Cake get() { 
    return new Cake(id); 
    } 
} 

class FrostCakes implements Function<Cake, Frosted> { 
    @Override 
    public Frosted apply(Cake cake) { 
    return new Frosted(cake); 
    } 
} 

class DecorateCakes implements Consumer<Frosted> { 
    public Decorated result; 
    @Override 
    public void accept(Frosted fc) { 
    result = new Decorated(fc); 
    } 
} 

public class Test { 
    public static int NUM_OF_CAKES = 20; 
    public static void main(String[] args) { 
    // Change from the default number of threads: 
    System.setProperty(
     "java.util.concurrent.ForkJoinPool" + 
     ".common.parallelism", "" + NUM_OF_CAKES); 

    // Test/demonstrate the decorator pattern: 
    List<Cake_> decorated = 
     IntStream.range(0, NUM_OF_CAKES) 
     .mapToObj(Cake::new) 
     .map(Frosted::new) 
     .map(Decorated::new) 
     .collect(Collectors.toList()); 
    decorated.forEach(System.out::println); 

    // Build cakes in parallel: 
    List<CompletableFuture<?>> futures = 
     IntStream.range(0, NUM_OF_CAKES) 
     .mapToObj(id -> new CreateCakes(id)) 
     .map(CompletableFuture::supplyAsync) 
     .thenApply(new FrostCakes()) 
     .thenAccept(new DecorateCakes()) 
     .collect(Collectors.toList()); 
    futures.forEach(CompletableFuture::join); 
    } 
} 

私はfuturesリストの定義の中でいくつかの基本的な理解が欠けている実現が、私は何を表示することを含めましたI 'これを達成しようとする:ケーキ製造プロセスの一部が並行して実行されるケーキ工場。

+0

コンパイルエラーが表示されたら、コンパイルエラーを投稿してください。 –

+0

ストリーム上でthenApple()を呼び出しています。 Streamには、thenApply()メソッドはありません。 –

答えて

3

あなたの質問に迅速に答えが(map(CompletableFuture::supplyAsync))上記の行から結果がStream<CompletableFuture<Cake>>ないCompletableFuture<Cake>返すためthenApplyラインがコンパイルされないことになります。 map(cakeFuture -> cakeFuture.thenApply(new FrostCakes()))のような操作をする必要があります。

しかし、私がなされる必要がある多くの重要なポイントだと思います。

あなたの例が教育目的のためのものであれば、もう1日か2日を準備に、具体的にはストリーム操作の基本についてはCompletableFutureを読むことをお勧めします。

この方法では、自分のマテリアルを発表するときには自信を持って感じることができますが、もっと重要なのは、同僚や生徒に危害を及ぼす可能性のある完全なコード例を提示しないことです。 CompletableFuture(さらにはデコレータ)を使用してください。

私はあなたの例で再実行する必要があると思うもののいくつかを指摘します。

  1. ForkJoinPoolの並列度を手動で設定することは、常に良い方法ではありません。デフォルトでは、それはかなり良いデフォルトであるRuntime.availableProcessors()によって返されるように、プロセッサの数を使用します。ほとんどの場合、冗長スレッドのスケジューリングとメンテナンスから不必要なオーバーヘッドが導入されるだけなので、それ以上のものに変更する必要があります。そして、あなたが発射しようとしているタスクの数に変更することは、ほとんど常に悪い考えです(説明は省略されています)。
  2. ストリームの例はいくつかのストリーム操作を実行し、その後でコレクションを終了し、ストリーム操作が収集されたリストに対して実行されます。最終的なマッピングによって返されたストリームにforEachを直接適用することで、コレクションのコレクションを使わずに書き直すことができます。これは、Java 8ストリームを使用した流暢なプログラミングモデルのよりよいデモンストレーションとなるでしょう。
  3. あなたの例も、並行して操作を実行しません。あなたはIntStream.range().parallel()を追加することにより、簡単にそれを修正することができますが、上からリストする冗長なコレクションを削除しない限り、あなたはちょうどforEachと、リストの内容を印刷して並列に何かをやったことを見ることはできません。
  4. java.util.functionインターフェイスを実装するクラスはあまり慣れていません。私はあなたの2番目の例が若干書き換えられない限り、ラムダで一口のラムダが生じるかもしれないが、あなたのケースでは対応するラムダ式に置き換えなければならないと主張するだろう。あなたのストリーム処理のこの段階で作成した、つや消しと装飾されたケーキへの参照を失うよう
  5. CompletableFuture.thenAcceptは、CompletableFuture<Void>を返します。あなたが気にしていない場合や、デコレーションロジックに何かを記録しても、あなたの例では、最終的に収集されたCompletableFutureのリストがケーキに到達するのを簡単に欺くことができますすべて、誰も彼のケーキを持っていないとそれを食べることを望んでいない)。

だからあなたの最初の例では、ケーキのIDがあるため、並列実行を命じていませんか

IntStream.range(0, NUM_OF_CAKES) 
     .parallel() 
     .mapToObj(Cake::new) 
     .map(Frosted::new) 
     .map(Decorated::new) 
     .forEach(System.out::println); 

お知らせのようなものを見ることができます。