JAVA学習ノート(三)-同時プログラミングCallable Future CompleableFuture


Runnableはインタフェースで、run()というメソッドしか宣言されていません.戻り値はvoidなので実行済みの結果は得られません.共有変数やスレッド通信でしかできません.
// 
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Callableも同様に1つのインタフェースにすぎず,1つのメソッドcall()のみを宣言し,彼が汎用インタフェースであることがわかり,callメソッドは結果タイプVを返す.
@FunctionalInterface
public interface Callable {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Futureとは、具体的なRunableまたはCallableタスクの実行結果をキャンセルし、完了したかどうかを照会し、結果を取得することです.
public interface Future {
    // , true,   false,  mayInterruptIfRunning ,
    boolean cancel(boolean mayInterruptIfRunning);
    // 
    boolean isCancelled();

    // 
    boolean isDone();

    // , , 
    V get() throws InterruptedException, ExecutionException;

    // , null
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

FutureTaskはRunnableFutureインタフェースを実現し,RunableFutureインタフェースはRunableとFutureインタフェースを継承しているので,スレッドによって実行されてもよいし,FutureとしてCallableの戻り値を得ることもできる.
public class FutureTask<V> implements RunnableFuture<V>;


public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

Callabel Futureの例
// Callabel 
public class CallabeTask implements Callable {

    @Override
    public Integer  call() throws Exception {
        System.out.println(" CallableTask");
        Thread.sleep(3000);
        System.out.println(" ");  
        return 1;
    }

}
// 
public class test {
    public static void main(String[] args) throws InterruptedException, ExecutionException{
        ExecutorService excutor=Executors.newCachedThreadPool();
        CallabeTask task=new CallabeTask();
        Future result=excutor.submit(task);
        excutor.shutdown();
        System.out.println(" ");
        System.out.println(" "+result.get());
    }
}

実行結果:CallableTaskメインスレッドを呼び出しサブスレッド計算完了サブスレッド結果1 CallableとFutureTaskを実行
public class test {
    public static void main(String[] args) throws InterruptedException, ExecutionException{
ExecutorService excutor=Executors.newCachedThreadPool();
        CallabeTask task=new CallabeTask();
        FutureTask futureTask=new FutureTask(task);
        excutor.submit(futureTask);
        excutor.shutdown();
        System.out.println(" ");
        System.out.println(" "+futureTask.get());
        }
}

実行結果:メインスレッド実行呼び出しCallableTaskサブスレッド計算完了サブスレッド結果1 CompletableFuturesはjava 8に新たに追加されたクラスで、主に非同期処理に使用されます.
public class test {
    public static void main(String[] args) throws InterruptedException, ExecutionException{
    // 
    ExecutorService excutor=Executors.newFixedThreadPool(5);
    // CompletableFuture , 
        CompletableFuture resultFuture=CompletableFuture.supplyAsync(()->{

            System.out.println("completableFuture 1 running");
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("completableFuture 1 complete");

            return "hello completablefuture";
        },excutor);
        System.out.println(" main thread complete");
// Future get() 。
        System.out.println(resultFuture.get());
    }
    }
}

CompletableFutureはget()メソッドを呼び出して実行結果を取得するだけでなく、コールバック関数を使用して処理結果を得ることもできます.
ExecutorService excutor=Executors.newFixedThreadPool(5);
        CompletableFuture resultFuture=CompletableFuture.supplyAsync(()->{

            System.out.println("completableFuture 1 running");
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("completableFuture 1 complete");

            return "hello completablefuture";
        },excutor);
        System.out.println(" main thread complete");
        //   thenAccept , ,thenAcceptAsync 
        resultFuture.thenAcceptAsync((m)->{
            System.out.println(m);
            System.out.println("Get Result by Back Function ");
        });

    }

CompletableFutureでは、completeExceptionally関数を使用して例外通知を発行できます.また、宣言例外処理も表示できます.
ExecutorService excutor=Executors.newFixedThreadPool(5);
        CompletableFuture resultFuture=CompletableFuture.supplyAsync(()->{

            System.out.println("completableFuture 1 running");
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("completableFuture 1 complete");

            return "hello completablefuture";
        },excutor);
        System.out.println(" main thread complete");
        resultFuture.thenAcceptAsync((m)->{
            System.out.println(m);
            System.out.println("thenaccept running");
            // 
        }).exceptionally((t)->{
            System.out.println(" ");
            System.out.println(t.getMessage());
            return null;
        });
        // 
        resultFuture.completeExceptionally(new Exception(" "));
        System.out.println(resultFuture.get());

thenApplyメソッドは、複数のfutureを組み合わせることができます.
ExecutorService excutor=Executors.newFixedThreadPool(5);
        CompletableFuture resultFuture=CompletableFuture.supplyAsync(()->{

            System.out.println("resultFuture"+Thread.currentThread().getName());

            System.out.println("resultFuture");
            return "hello result1";
        },excutor);
        CompletableFuture<Integer> resultFuture1=resultFuture.thenApplyAsync((t)->{
            System.out.println("resultFuture1"+Thread.currentThread().getName());
            System.out.println("resultFuture1");
            return t.length();
        },excutor);
        CompletableFuture<Double> resultFuture2=resultFuture1.thenApplyAsync(r->{
            System.out.println("resultFuture2"+Thread.currentThread().getName());
            return r*2.0;},excutor);
        System.out.println(resultFuture2.get());

CompletableFutureには、さまざまなニーズシーンを満たす方法がたくさんあります.具体的な方法は、使用するときに具体的な分析を行う必要があります.CompletableFutureの背後には、Fork/joinフレームワーク(まだ深く理解されていない)によって、非同期と同時実行が実現されています.