最近在学习过程中了解到了CompletableFuture异步编排,感觉很好用。(不过我还是更习惯使用传统方式控制多线程)
还没有看过源码,想试试能不能简单实现部分功能。如果你发现代码的问题希望指出。
暂时实现了supplyAsync()
whenCompleteAsync()
和 exceptionally()
。
1 实现
- 起名叫SimpleCompletableFuture
public class SimpleCompletableFuture<T> implements Future { ... }
- 成员变量
除了自己使用的锁等对象之外都要使用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);
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(); } }
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); }
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; } }
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;
}
}