多線程設計模式---Future設計模式(筆記)

多線程設計模式---Future設計模式


自從jdk1.5之後,java提供了一個比較強大的Future。主要用於解決執行時間比較長的任務。通常需要等待任務執行結束或者出錯才能返回結果。
Future類圖

接口定義

Future接口定義

package com.jiang.currents.future;

/**
 * @Description 獲取計算呢結果和判斷任務是否完成兩個接口
 * @createTime 2019年10月31日
 */
public interface Future<T> {
    // 返回計算後的結果,該方法會陷入阻塞狀態
    T get() throws  InterruptedException ;

    // 判斷任務是否已經被完成
    boolean done();
}

FutureService接口定義

package com.jiang.currents.future;

/**
 * @ClassName FutureService.java
 * @Description FutureService主要用於提交任務
 * @createTime 2019年10月31日
 */
public interface FutureService<IN,OUT> {
    // 接受不需要返回值的任務,future.get()會獲得null
    Future<?> submit(Runnable runnable);

    // 提交需要返回值的任務,Task接口替代了Runnable接口
    Future<OUT> submit(Task<IN, OUT> task, IN input);

    // 提交需要返回值的任務 回調函數
    Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback);


    // 使用靜態方法構建一個FutureService
    static <T, R> FutureService<T, R> newService() {
        return new FutureServiceImpl<>();
    }
}

Task接口設計

package com.jiang.currents.future;

/**
 * @ClassName Task.java
 * @Description Task接口主要是體提供給調用者實現計算邏輯使用的
 * @createTime 2019年10月31日
 */
public interface Task<IN, OUT> {
    // 給定一個參數,經過計算返回結果
    OUT get(IN input);
}

Callback回調接口

package com.jiang.currents.future;

/**
 * @ClassName Callback.java
 * @Description TODO
 * @createTime 2019年10月31日
 */
public interface Callback<T> {
    //任務完成後會調用該方法, 其中T爲任務執行後的結果
    void call(T t);
}

程序實現

FutureTask是Future的一個實現,除了實現Future中定義的get()以及done()方法。還額外增加了protected方法finish方法

package com.jiang.currents.future;

/**
 * @ClassName FutureTask.java
 * @Description TODO
 * @createTime 2019年10月31日
 */
public class FutureTask<T> implements Future<T> {

    // 計算結果
    private T result;

    // 是否已經完成
    private boolean isDone = false;

    // 定義對象鎖
    private final Object LOCK = new Object();

    @Override
    public T get() throws InterruptedException {
        synchronized (LOCK) {
            // 當任務還沒有完成時,調用get方法被掛起,進入阻塞
            while (!isDone) {
                LOCK.wait();
            }

        }
        // 計算返回結果
        return result;
    }
    //設置計算結果
    protected void finish(T result) {
        synchronized (LOCK) {
            if (isDone) {
                return;
            }
            #計算完成,並將isDone 設置爲true,同時喚醒阻塞中的線程
            this.result = result;
            this.isDone = true;
            LOCK.notifyAll();
        }

    }
    @Override
    public boolean done() {
        return isDone;
    }
}

FutureServiceImpl

package com.jiang.currents.future;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 當提交任務的時候,創建一個信息的線程來受理該任務,進而達到任務異步執行的效果
 *
 * @param <IN>
 * @param <OUT>
 */
public class FutureServiceImpl<IN, OUT> implements FutureService<IN, OUT> {
    // 爲執行的線程指定名字前綴
    private final static String FUTURE_THREAD_PREFIX = "FUTURE-";

    private final AtomicInteger nextCounter = new AtomicInteger(0);

    private String getNextName() {
        return FUTURE_THREAD_PREFIX + nextCounter.getAndIncrement();
    }
    @Override
    public Future<?> submit(Runnable runnable) {
        final FutureTask<Void> future = new FutureTask<>();
        new Thread(() -> {
            runnable.run();
            future.finish(null);

        }, getNextName()).start();
        return future;
    }

    @Override
    public Future<OUT> submit(Task<IN, OUT> task, IN input) {
        final FutureTask<OUT> future = new FutureTask<>();
        new Thread(() -> {
            OUT result = task.get(input);
            //  設置返回結果
            future.finish(result);

        }, getNextName()).start();
        return future;
    }
    @Override
    public Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback) {
        final FutureTask<OUT> future = new FutureTask<>();
        new Thread(() -> {
            OUT result = task.get(input);
            //  設置返回結果
            future.finish(result);
            if (null != callback) {
                //  回調函數
                callback.call(result);
            }

        }, getNextName()).start();
        return future;
    }
}

Future主要是耗費時間的操作交給另外一個線程執行,從而達到異步的目的,而不是阻塞等待結果的返回。

import java.util.concurrent.TimeUnit;

/**
 * @ClassName FutureTest01.java
 * @Description 提交無返回值的任務
 * @createTime 2019年10月31日
 */
public class FutureTest01 {
    public static void main(String[] args) throws InterruptedException {
        FutureService<Void, Void> service = FutureService.newService();

        Future<?> future = service.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I am finish done .");

        });
        //get 方法 會使當前線程進入阻塞狀態
        future.get();
    }
}
package com.jiang.currents.future;

import java.util.concurrent.TimeUnit;
/**
 * @ClassName FutureTest02.java
 * @Description 提交有返回值的任務
 * @createTime 2019年10月31日
 */
public class FutureTest02 {
    public static void main(String[] args) throws InterruptedException {
        //定義一個有返回值的FutureService
        FutureService<String, Integer> service = FutureService.newService();
        //submitf方法立即返回
        Future<Integer> future = service.submit(input -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return input.length();

        }, "Hello");
        //get 方法 會使當前線程進入
        System.err.println(future.get());
    }
}

在這裏插入圖片描述

package com.jiang.currents.future;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName FutureTest03.java
 * @Description 提交有返回值的任務 支持回調函數
 * @createTime 2019年10月31日
 */
public class FutureTest03 {
    public static void main(String[] args) throws InterruptedException {
        FutureService<String, Integer> service = FutureService.newService();

        Future<Integer> future = service.submit(input -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return input.length();

        }, "Hello", System.out::println);
    }
}

在這裏插入圖片描述使用任務完成時hi回調機制可以讓調用者不在進行顯示get方式獲取數據而進入阻塞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章