2016-05-02 12 views
4

CompletableFutureのsupplyAsync()内で長時間実行される操作を処理し、thenAccept()に結果を取得します。いくつかの時間でthenAccept()はメインスレッドで実行しますが、それはワーカースレッドで実行しています。しかし、私はthenAccept()操作をメインスレッドでのみ実行します。これはサンプルコードです。なぜCompletableFutureのthenAccept()がメインスレッドで実行されていない

private void test() { 

    ExecutorService executorService = Executors.newSingleThreadExecutor(); 

    CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> { 
     System.out.println("supplyAsync | I am running on : " + Thread.currentThread().getName()); 
     return "Hello world"; 
    }, executorService); 

    CompletableFuture<Void> cf3 = cf1.thenAccept(s -> { 
     System.out.print("thenAccept | I am running on : " + Thread.currentThread().getName()); 
     System.out.println(" | answer : " + s); 
    }); 

    cf3.thenRun(() -> { 
     System.out.println("thenRun | I am running on : " + Thread.currentThread().getName()); 
     System.out.println(); 
    }); 

} 

public static void main(String[] args) { 

    App app = new App(); 
    for(int i = 0; i < 3; i++){ 
     app.test(); 
    } 
} 

結果は次のとおりです。

supplyAsync | I am running on : pool-1-thread-1 
thenAccept | I am running on : main | answer : Hello world 
thenRun | I am running on : main 

supplyAsync | I am running on : pool-2-thread-1 
thenAccept | I am running on : main | answer : Hello world 
thenRun | I am running on : main 

supplyAsync | I am running on : pool-3-thread-1 
thenAccept | I am running on : pool-3-thread-1 | answer : Hello world 
thenRun | I am running on : pool-3-thread-1 

がどのように私はこの問題を解決することができますか?

+0

なぜそれをしたいですか? – sisyphus

+0

ありがとうございます。側では、thenAccept()メソッドが共有リソースにアクセスすると仮定します。次に、私はリソースのスレッドの安全性について考慮する必要があります。 Vert.xのexecuteBlockingはこれに似ています。彼らはこれを適切に処理します。 – Tharanga

+0

さて、「正しく」、見る人の目の中にいるかもしれません。非同期の方法で共有リソースにアクセスする場合は、スレッドの安全性を心配する必要があるようです。おそらく、単一のスレッド上でタスクをスケジュールするモニターを介して共有リソースへのアクセスのみを許可するべきです。 – sisyphus

答えて

1

JavaDocでCompletableFutureを見てください。興味深い部分はCompletionStageに関するポリシーです。

あり

あなたはどちらか、またはシナリオの種類に非非同期法の結果を使用していることを見つけます。実装を見てみると、Javaランタイムの非公開部分で終わることになります。何らかの種類の競合状態が発生する可能性があることを意味する何らかのUNSAFEの処理があります。

私は thenAcceptAsync()thenRunAsyncを(使用することをお勧め

変種との両方の呼び出しにごExecutorServiceの変数を渡します。

+0

すべての 'CompletableFuture'タスクが完了する前にメインスレッドが終了しますか?また、 'CompletableFuture' javadocの '面白い部分'を投稿できますか? –