【练习/Java并发】实现CompletableFuture简单版

最近在学习过程中了解到了CompletableFuture异步编排,感觉很好用。(不过我还是更习惯使用传统方式控制多线程)
还没有看过源码,想试试能不能简单实现部分功能。如果你发现代码的问题希望指出。
暂时实现了supplyAsync() whenCompleteAsync()exceptionally()

1 实现

  1. 起名叫SimpleCompletableFuture
    public class SimpleCompletableFuture<T> implements Future {
    	...
    }
    
  2. 成员变量
    除了自己使用的锁等对象之外都要使用volatile保证异步线程对结果更新的可见性。
    // 保存自己的运算结果
    private volatile T result;
    // 保存异常
    private volatile Throwable throwable;
    // 任务完成标志
    private volatile boolean done;
    // 是否是异步任务
    private volatile boolean async;
    // 锁
    private final Lock lock = new ReentrantLock();
    // 条件变量
    private final Condition condition = lock.newCondition();
    // 整个类共用一个线程池来执行
    private final static ExecutorService pool = Executors.newFixedThreadPool(10);
    
  3. supplyAsync方法
    这是一个静态方法,可以作为异步编排的开始,得到一个SimpleCompletableFuture对象。
    public static <U> SimpleCompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        SimpleCompletableFuture<U> future = new SimpleCompletableFuture<>();
        future.async = true;
        pool.submit(() -> {
            // 开启线程异步执行
            try {
                future.result = supplier.get();
            } catch (Throwable thr) {
                future.throwable = thr;
            } finally {
                future.done = true;
                // 通知所有等待自己完成的线程
                notifyAllOnCondition(future);
            }
        });
        return future;
    }
    
    private static void notifyAllOnCondition(SimpleCompletableFuture<?> future) {
        future.lock.lock();
        try {
            future.condition.signalAll();
        } finally {
            future.lock.unlock();
        }
    }
    
  4. whenCompleteAsync方法
    public SimpleCompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) {
        SimpleCompletableFuture<T> nextFuture = copyUndone();
        pool.submit(() -> {
            waitForDone();
            nextFuture.result = this.result;
            nextFuture.throwable = this.throwable;
            // 任务已经完成了
            action.accept(this.result, this.throwable);
            // 设置完成标志位,通知等待线程
            finishWork(nextFuture);
        });
        nextFuture.async = true;
        return nextFuture;
    }
    
    // 就是用来复制一个this但是完成标志为false
    private SimpleCompletableFuture<T> copyUndone() {
       SimpleCompletableFuture<T> newFuture = new SimpleCompletableFuture<>();
        newFuture.result = this.result;
        newFuture.throwable = this.throwable;
        newFuture.async = this.async;
        newFuture.done = false;
        return newFuture;
    }
    
    private void waitForDone() {
        lock.lock();
        try {
            while (!done) {
                try {
                    condition.await();
                } catch (InterruptedException ignored) {
                }
            }
        } finally {
            lock.unlock();
        }
    }
    
    private void finishWork(SimpleCompletableFuture<?> future) {
        future.done = true;
        notifyAllOnCondition(future);
    }
    
  5. exceptionally方法
    public SimpleCompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn) {
        if (async) {
            SimpleCompletableFuture<T> nextFuture = copyUndone();
            pool.submit(() -> {
                waitForDone();
                if (this.throwable != null) {
                    nextFuture.result = fn.apply(throwable);
                }
                finishWork(nextFuture);
            });
            return nextFuture;
        } else {
            waitForDone();
            if (this.throwable != null) {
                this.result = fn.apply(throwable);
            }
            return this;
        }
    }
    
  6. get方法
    @Override
    public T get() {
        waitForDone();
        return this.result;
    }
    

2 测试

class Test {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
        SimpleCompletableFuture<Integer> future = SimpleCompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            int a = 1 / 0;
            return a;
        }).whenCompleteAsync((result, exception) -> {
            System.out.println(sdf.format(new Date()) + " --- " + exception.getClass().getName());
        }).exceptionally(exception -> {
            return 1;
        });
        System.out.println(sdf.format(new Date()) + " --- main at 32");
        System.out.println("get: " + future.get());
    }
}

输出

52:32 --- main at 32
52:34 --- java.lang.ArithmeticException
get: 1

3 完整代码

package completable;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author dujianzhang
 */
class Test {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
        SimpleCompletableFuture<Integer> future = SimpleCompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            int a = 1 / 0;
            return a;
        }).whenCompleteAsync((result, exception) -> {
            System.out.println(sdf.format(new Date()) + " --- " + exception.getClass().getName());
        }).exceptionally(exception -> {
            return 1;
        });
        System.out.println(sdf.format(new Date()) + " --- main at 32");
        System.out.println("get: " + future.get());
    }
}

public class SimpleCompletableFuture<T> implements Future {

    private volatile T result;
    private volatile Throwable throwable;
    private volatile boolean done;
    private volatile boolean async;
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private final static ExecutorService pool = Executors.newFixedThreadPool(10);

    public static <U> SimpleCompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        SimpleCompletableFuture<U> future = new SimpleCompletableFuture<>();
        future.async = true;
        pool.submit(() -> {
            // 开启线程异步执行
            try {
                future.result = supplier.get();
            } catch (Throwable thr) {
                future.throwable = thr;
            } finally {
                future.done = true;
                notifyAllOnCondition(future);
            }
        });
        return future;
    }

    public SimpleCompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) {
        SimpleCompletableFuture<T> nextFuture = copyUndone();
        pool.submit(() -> {
            waitForDone();
            nextFuture.result = this.result;
            nextFuture.throwable = this.throwable;
            // 任务已经完成了
            action.accept(this.result, this.throwable);
            finishWork(nextFuture);
        });
        nextFuture.async = true;
        return nextFuture;
    }

    public SimpleCompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn) {
        if (async) {
            SimpleCompletableFuture<T> nextFuture = copyUndone();
            pool.submit(() -> {
                waitForDone();
                if (this.throwable != null) {
                    nextFuture.result = fn.apply(throwable);
                }
                finishWork(nextFuture);
            });
            return nextFuture;
        } else {
            waitForDone();
            if (this.throwable != null) {
                this.result = fn.apply(throwable);
            }
            return this;
        }
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        // TODO
        return false;
    }

    @Override
    public boolean isCancelled() {
        // TODO
        return false;
    }

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

    @Override
    public T get() {
        waitForDone();
        return this.result;
    }

    @Override
    public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        // TODO
        return null;
    }

    private void waitForDone() {
        lock.lock();
        try {
            while (!done) {
                try {
                    condition.await();
                } catch (InterruptedException ignored) {
                }
            }
        } finally {
            lock.unlock();
        }
    }

    private static void notifyAllOnCondition(SimpleCompletableFuture<?> future) {
        future.lock.lock();
        try {
            future.condition.signalAll();
        } finally {
            future.lock.unlock();
        }
    }

    private void finishWork(SimpleCompletableFuture<?> future) {
        future.done = true;
        notifyAllOnCondition(future);
    }

    private SimpleCompletableFuture<T> copyUndone() {
        SimpleCompletableFuture<T> newFuture = new SimpleCompletableFuture<>();
        newFuture.result = this.result;
        newFuture.throwable = this.throwable;
        newFuture.async = this.async;
        newFuture.done = false;
        return newFuture;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值