JAVA异步编程
java 5前时代
并发实现
- Java Green Thread
- Java Native Thread
编程模型
-
Thread
-
Runnable
使用join()实现线程同步
实现局限性
- 缺少线程管理的原生支持
- 缺少"锁"API
- 缺少知悉选哪个完成的原生支持
- 执行结果获取困难
- Double Check Locking 不确定性
public class BeforeJava5 {
public static void main(String[] args) throws InterruptedException {
// 创建线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.printf("当前线程 Thread:%s, hello world...\n",Thread.currentThread().getName());
}
});
// 启动线程
thread.start();
// 串行化操作
thread.join();
System.out.printf("当前线程 Thread:%s, start...\n",Thread.currentThread().getName());
}
}
java 5时代
并发框架
- J.U.C = java.util.concurrent
并发编程模型
- Executor
- Runnable、Callable
- Future
java 7时代
并行框架
- Fork/join
编程模型
- ForkJoinPool
- ForkJoinTask
- RescursiveAction
FUture的限制
- 无法手动完成
- 阻塞式结果返回
- 无法链式多个Future
- 无法合并多个Future结果
- 缺少异常处理
public class ForkJoinDemo1 {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
// 分为 Runnable 和 Callable, 前者无返回值,后者有
Future<String> future = forkJoinPool.submit(new Callable() {
@Override
public Object call() throws Exception {
return "hello world";
}
});
String value = future.get();
System.out.println(value);
}
}
public class ForkJoinDemo2 {
public static void main(String[] args) {
/** 4核 **/
System.out.printf("当前公用 ForkJoin 线程池 并行数:%d\n",ForkJoinPool.commonPool().getParallelism());
System.out.printf("当前CPU 处理器数:%d\n",Runtime.getRuntime().availableProcessors());
// 创建线程池
ForkJoinPool forkJoinPool = new ForkJoinPool();
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
AtomicInteger atomicInteger = new AtomicInteger();
// 创建task实现
RecursiveAction recursiveAction = new Task(integers, atomicInteger);
//提交并执行
forkJoinPool.invoke(recursiveAction);
// 关闭任务
forkJoinPool.shutdown();
System.out.println("运行结果: " + atomicInteger);
}
private static class Task extends RecursiveAction {
private final List<Integer> integers;
private final AtomicInteger atomicInteger;
Task(List<Integer> integers, AtomicInteger atomicInteger) {
this.integers = integers;
this.atomicInteger = atomicInteger;
}
@Override
protected void compute() {
// 组装执行参数
int size = integers.size();
if (size >1){
int part = size / 2;
List<Integer> leftPart = integers.subList(0, part);
Task task1 = new Task(leftPart, atomicInteger);
List<Integer> rightPart = integers.subList(part, size);
Task task2 = new Task(rightPart, atomicInteger);
// fork/join 实现串行化
invokeAll(task1,task2);
}else {
if (size == 0){
return;
}
Integer num = integers.get(0);
//累加
atomicInteger.addAndGet(num);
}
}
}
}
Future 异步实现扩展
Netty Future
public class NettyFutureDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println("netty future 异步实现开始...");
long l = System.currentTimeMillis();
// 初始化线程池
EventExecutorGroup group = new DefaultEventExecutorGroup(4); // 4 threads
Future<Integer> f = group.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.err.println("执行耗时操作...");
dealSomeThing();
return 100;
}
});
f.addListener(new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> objectFuture) throws Exception {
System.err.println("计算结果::"+objectFuture.get());
}
});
System.err.println("计算耗时:" + (System.currentTimeMillis() - l)+" ms");
// 关闭线程池
group.shutdownGracefully();
System.out.println("netty future 异步实现结束...");
}
static void dealSomeThing() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Guava Future
public class GuavaFutureDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println("guava future 异步实现开始...");
long l = System.currentTimeMillis();
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
ListenableFuture<Integer> future = service.submit(new Callable<Integer>() {
public Integer call() throws Exception {
System.out.println("执行耗时操作...");
dealSomeThing();
return 100;
}
});
Futures.addCallback(future, new FutureCallback<Integer>() {
public void onSuccess(Integer result) {
System.out.println("计算结果:" + result);
}
public void onFailure(Throwable throwable) {
System.out.println("异步处理失败,e=" + throwable);
}
});
System.out.println("算耗时:"计 + (System.currentTimeMillis() - l)+" ms");
System.out.println("guava future 异步实现结束...");
}
static void dealSomeThing() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Future 有两种模式:将来式和回调式。而回调式会出现回调地狱的问题,由此衍生出了 Promise 模式来解决这个问题。这才是 Future 模式和 Promise 模式的相关性。
java 8时代
异步并行框架
- Fork/join
编程模型
- CompletionStage
- CompletableFuture
- 使用 CompletableFuture 解决回调地狱问题 (Callback Hell)
public class CompletableFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1. 完成操作可以被其他线程去做
// CompletableFuture<String> completableFuture = new CompletableFuture<>();
// completableFuture.complete("hello world");
// String value = completableFuture.get();
// System.out.printf("当前线程 Thread:%s,hello world... %s\n",Thread.currentThread().getName(),value);
// 2. 异步执行,阻塞操作
// CompletableFuture runAsyncCompletableFuture = CompletableFuture.runAsync(()->{
// String name = Thread.currentThread().getName();
// System.out.println("Thread: " + name + " --hello world");
// });
// //保证执行顺序 hello world 输出在前 实际上还是阻塞主线程
// runAsyncCompletableFuture.get();
// System.out.println("staring...");
// 3. 异步执行,非阻塞操作
// CompletableFuture<String> supplyAsyncCompletableFuture = CompletableFuture.supplyAsync(()->{
// // 假设是耗时操作 如:数据库查询
// return String.format("当前线程 Thread:%s, hello world...\n",Thread.currentThread().getName());
// });
// String value = supplyAsyncCompletableFuture.get();
// System.out.println("value = " + value);
// System.out.println("staring...");
// 4. 合并操作
CompletableFuture combainCompletableFuture = CompletableFuture.supplyAsync(()->{
// 假设是耗时操作 如:数据库查询
return String.format("当前线程 Thread:%s, hello world...\n",Thread.currentThread().getName());
}).thenApply(value ->{
return value + "数据库查询";
}).thenApply(value ->{
return value + LocalDate.now();
}).thenApply(value ->{
System.out.printf("当前线程 Thread:%s, hello world...\n",Thread.currentThread().getName());
return value;
}).thenRun(() ->{
System.out.println("操作完成");
throw new RuntimeException("抛一个异常");
// Java 8 异常处理
}).exceptionally(e -> {
System.out.println(e);
return null;
});
combainCompletableFuture.get();
System.out.println("staring...");
while (!combainCompletableFuture.isDone()){}
}
}
spring 自身实现
主类:ListenableFuture
实现类:ListenableFutureTask
- 主要实现部分代码
private final Queue<SuccessCallback<? super T>> successCallbacks = new LinkedList<SuccessCallback<? super T>>();
public void addCallback(ListenableFutureCallback<? super T> callback) {
Assert.notNull(callback, "'callback' must not be null");
synchronized (this.mutex) {
switch (this.state) {
case NEW:
this.successCallbacks.add(callback);
this.failureCallbacks.add(callback);
break;
case SUCCESS:
notifySuccess(callback);
break;
case FAILURE:
notifyFailure(callback);
break;
}
}
}
Reactive Streams
时代局限性(Java 9 之前)
- 阻塞编程
- 无法并行计算
- 资源低效利用
- 异步编程
- Callback
- Future
四种角色
- Publisher:发布者
- Subscriber:订阅者
- Subscription:订阅的控制器
- Processor:发布者|订阅者
Reactive Streams规范
对比Iterator模式
- 数据方向
- Reactive Streams: 推模式(Push)
- Iterator:拉模式(Pull)
- 编程模式
- Reactive Streams:发布订阅模式(Publish-Subscriber)
- Iterator:命令编程模式(Imperative)
- 信号
- onSubscribe():订阅事件
- onNext():是数据到达事件‘
- onComplete():订阅完成事件
- onError:订阅异常
- request():请求
- cnacel():取消
- 核心接口
- Mono: 异步0-1元素序列,Future<Optional<?>>
- Flux:异步0-N元素系列:Future<Collection<>>
- 编程模式
- 接口编程
- 函数式编程