2016-05-25 20 views
4

私はこの質問に答えました:Executing Dependent tasks in parallel in Java future.get()を使用して現在のスレッドをブロックしています。一度にたくさんのgets()が呼び出されます。 Javaの先物から先物をどのように構成するのですか?ブロッキングなしでJava 8で依存するタスクを実行する方法

+0

通常、「.get()」はバリアです。結果が得られない場合は、それ以上計算することはできません。 –

+0

はい、先物から先物を構成することはできますが、回答を参照してください。 – Snickers3192

+0

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.htmlを参照してください。それは逐次実行を行うことができます。 –

答えて

3

私は自分自身でこの質問に答えると思っていました.Futuresの代わりにJavaでCompletableFuturesを使用することができます。 CompletableFuturesは、scalasのflatMapに似ているthenCombineメソッドによる合成を可能にします。今やブロッキングは発生せず、最速の時間を達成するためには3つのスレッドしか必要ありません。

import java.util.concurrent.CompletableFuture; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.function.BiFunction; 
import java.util.function.Supplier; 

public class Barrista 
{ 

    // number of threads used in executor 
    static final int NOTHREADS = 3; 

    // time of each task 
    static final int HEATWATER = 1000; 
    static final int GRINDBEANS = 1000; 
    static final int FROTHMILK = 1000; 
    static final int BREWING = 1000; 
    static final int COMBINE = 1000; 

    // method to simulate work (pause current thread without throwing checked exception) 
    public static void pause(long t) 
    { 
     try 
     { 
      Thread.sleep(t); 
     } 
     catch(Exception e) 
     { 
      throw new Error(e.toString()); 
     } 
    } 

    // task to heat some water 
    static class HeatWater implements Supplier<String> 
    { 
     @Override 
     public String get() 
     { 
      System.out.println("Heating Water"); 
      pause(HEATWATER); 
      return "hot water"; 
     } 
    } 

    // task to grind some beans 
    static class GrindBeans implements Supplier<String> 
    { 
     @Override 
     public String get() 
     { 
      System.out.println("Grinding Beans"); 
      pause(GRINDBEANS); 
      return "grinded beans"; 
     } 
    } 

    // task to froth some milk 
    static class FrothMilk implements Supplier<String> 
    { 
     @Override 
     public String get() 
     { 
      System.out.println("Frothing some milk"); 
      pause(FROTHMILK); 
      return "some milk"; 
     } 
    } 

    // task to brew some coffee 
    static class Brew implements BiFunction<String,String, String> 
    { 
     @Override 
     public String apply(String groundBeans, String heatedWater) 
     { 
      System.out.println("Brewing coffee with " + groundBeans + " and " + heatedWater); 
      pause(BREWING); 
      return "brewed coffee"; 
     } 
    } 

    // task to combine brewed coffee and milk 
    static class Combine implements BiFunction<String,String, String> 
    { 
     @Override 
     public String apply(String frothedMilk, String brewedCoffee) 
     { 
      System.out.println("Combining " + frothedMilk + " "+ brewedCoffee); 
      pause(COMBINE); 
      return "Final Coffee"; 
     } 
    } 

    public static void main(String[] args) 
    { 
     ExecutorService executor = Executors.newFixedThreadPool(NOTHREADS); 

     long startTime = System.currentTimeMillis(); 

     try 
     { 
      // create all the tasks and let the executor handle the execution order 
      CompletableFuture<String> frothMilk =  CompletableFuture.supplyAsync(new FrothMilk(), executor); 
      CompletableFuture<String> heatWaterFuture = CompletableFuture.supplyAsync(new HeatWater(), executor); 
      CompletableFuture<String> grindBeans =  CompletableFuture.supplyAsync(new GrindBeans(), executor); 

      CompletableFuture<String> brew = heatWaterFuture.thenCombine(grindBeans, new Brew()); 
      CompletableFuture<String> coffee =   brew.thenCombine(frothMilk, new Combine()); 

      // final coffee 
      System.out.println("Here is the coffee:" + coffee.get()); 

      // analyzing times: 
      System.out.println("\n\n"); 
      System.out.println("Actual time: \t\t\t\t" + (System.currentTimeMillis() - startTime)/1000.0); 

      // compute the quickest possible time: 
      long path1 = Math.max(GRINDBEANS, HEATWATER)+ BREWING + COMBINE; 
      long path2 = FROTHMILK + COMBINE; 
      System.out.println("Quickest time multi-threaded:\t\t" + Math.max(path1, path2)/1000.0); 

      // compute the longest possible time: 
      long longestTime = HEATWATER + GRINDBEANS + FROTHMILK + BREWING + COMBINE; 
      System.out.println("Quickest time single-threaded thread:\t" + longestTime/1000.0); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     finally 
     { 
      executor.shutdown(); 
     } 

    } 
} 
2

は、Java 8はあなたが完了段階に依存コールバックをトリガーする以外、特に、getコールをブロックする必要はありませんCompletableFutureを、紹介します。明示的(その値と ステータスを設定)が完了してもよいし、その終了時にトリガー依存 機能および行動を支持する、CompletionStageとして使用することができる

A未来。 Javaの8の前にdocumentation

読むより、この概念はdocumentationとスプリングライブラリtooで続きを読む、Googleのグルーヴィーなライブラリで利用可能です。

+0

ありがとうございます。私はこれらを私の答えに使用しました。質問をするときに私はこの質問の答えを用意していましたが、それは人々にとって役に立つと思いました。私はこれを行う方法を見つけるのは非常に苦労しました。 – Snickers3192

関連する問題