Future 设计模式实现

x33g5p2x  于2022-04-20 转载在 其他  
字(2.9k)|赞(0)|评价(0)|浏览(208)

一 点睛

Future 简单理解:先给你一张凭证,等结果出来后,你再来取。

二 代码

1 Future

package concurrent.future;

public interface Future<T> {
    // 返回计算后的结果,该方法会陷入阻塞状态
    T get() throws InterruptedException;

    // 判断任务是否已经执行完成
    boolean done();
}

2 FutureService

package concurrent.future;

public interface FutureService<IN, OUT> {
    // 提交不需要返回值的任务,Future.get 方法返回的将会是 null
    Future<?> submit(Runnable runnable);

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

    // 使用静态方法创建一个  FutureService 实例
    static <T, R> FutureService<T, R> newService() {
        return new FutureServiceImpl<>();
    }
}

3 Task

package concurrent.future;

@FunctionalInterface
public interface Task<IN, OUT> {
    // 给定一个参数,经过计算返回结果
    OUT get(IN input);
}

4 FutureTask

package concurrent.future;

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;
        }
    }

    // 为 FutureTask 设置结算结果
    protected void finish(T result) {
        synchronized (Lock) {
            if (isDone) {
                return;
            }
            this.result = result;
            this.isDone = true;
            Lock.notifyAll();
        }
    }

    // 返回当前任务是否已经完成
    @Override
    public boolean done() {
        return isDone;
    }
}

5 FutureServiceImpl

package concurrent.future;

import java.util.concurrent.atomic.AtomicInteger;

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();
            // 任务结束之后将 null 作为结果传给 future
            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);
            // 任务结束之后,将真实的结果通过 finish 方法传递给 future
            future.finish(result);
        }, getNextName()).start();
        return future;
    }
}

三 测试

1 测试代码

package concurrent.future;

import java.util.concurrent.TimeUnit;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        // 定义不需要返回值的 FutureService
        FutureService<Void,Void> service = FutureService.newService();
        Future<?> futrue = service.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I am finish done");
        });
        // futrue 方法会使当前线程进入阻塞
        futrue.get();

        // 定义有需要返回值的 FutureService
        FutureService<String,Integer> service1 = FutureService.newService();
        Future<Integer> future1 = service1.submit(input ->
        {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return input.length();
        },"hello");
        System.out.println(future1.get());
    }
}

2 测试结果

I am finish done

5

创作挑战赛

新人创作奖励来咯,坚持创作打卡瓜分现金大奖

相关文章