当前位置 博文首页 > 白菜园:终于可以愉快的撸Java异步代码了!

    白菜园:终于可以愉快的撸Java异步代码了!

    作者:白菜园 时间:2021-01-18 16:05

    ??异步响应式编程可以极大的提高系统的并发呑吐量,但由于Java没有类似于其他语言的Async/Await机制,所以只能通过CompletableFuture.thenXXX()来串联各个异步任务,这给习惯了写同步增删改查的小伙伴们带来了些小麻烦。如果说C#基于状态机在编译时实现了await转换,那么Java肯定也可以基于相同的原理实现await,作者上网一搜果然找到了ea-async,使用与C#相同的方式实现了await异步方法,这回终于可以愉快的撸Java异步代码了。

    一、 示例代码

    ??举个扣减库存并保存订单的例子,在没有await方式下的示例代码如下:

    public CompletableFuture<?> saveOrder(Order order) {
        //1.开始事务
        return DataStore.DemoDB.beginTransaction().thenCompose(txn -> {
            //2.扣库存
            var cmd = new SqlUpdateCommand<Order>();
            cmd.update(e -> e.Stock = e.Stock - order.Quantity); //当前量扣除订单量
            cmd.where(e -> e.ProductId == order.ProductId);
            var outs = cmd.output(e -> e.Stock);
            return cmd.execAsync(txn).thenCompose(rows -> {
                //3.判断库存
                if (rows == 0 || outs.get(0) < 0) 
                    return CompletableFuture.failedFuture("库存不足");
                //4.保存订单
                return order.saveAsync(txn);
            }).thenCompose(r -> txn.commitAsync()); //5.递交事务
        }).thenApply(r -> "Done.");
    }
    

    ??WTF! 一层套一层的回调,这还只是个简单的例子啊。但是如果使用await的方式,业务逻辑就变得清爽多了:

    import static sys.Async.await;
    
    public CompletableFuture<?> saveOrder(Order order) {
        //1.开始事务
        var txn = await(DataStore.DemoDB.beginTransaction());
        //2.扣库存
        var cmd = new SqlUpdateCommand<Order>();
        cmd.update(e -> e.Stock = e.Stock - order.Quantity); //当前量扣除订单量
        cmd.where(e -> e.ProductId == order.ProductId);
        var outs = cmd.output(e -> e.Stock); 
        var rows = await(cmd.execAsync(txn));
        //3.判断库存
        if (rows == 0 || outs.get(0) < 0)
            return CompletableFuture.failedFuture("库存不足");
        //4.保存订单
        await(order.saveAsync(txn));
        //5.递交事务
        await(txn.commitAsync());
        return CompletableFuture.completedFuture("Done.");
    }
    

    二、 实现原理

    ??核心思想没有变,还是代码分析转换。作者原本想利用JDT在源码层进行await转换,但是工作量还是比较大的,在这里感谢github/ea-async项目,使得作者只修改了十几行代码就实现了上述效果,具体转换过程如下:

    1. 服务模型的虚拟代码经过JDT分析、转换、编译为class文件(参考前篇说明);
    2. 调用ea-async的Transformer类直接分析与转换class文件内的await方法调用,生成新的class文件。

    具体参考源码PublishService的compileService()及transformAsync()方法。

    三、 本篇小结

    ??先解释一下上篇"优雅的Java ORM"小伙伴们的评论,有说这么多ORM干吗还要造一个的,也有说不够"优雅"的,其实造轮子最根本的原因是:异步支持!,Spring WebFlux及VertX有相应的异步操作数据库的支持,但本框架没法集成。MyBatis之类的全是同步操作,小的应用系统没有问题,高并发系统的呑吐量就非常可怜了,这个大家可以测一下Spring MVC与WebFlux的性能对比。

    ??软件技术日新月异,新一代的开发框架必定是异步的!对于作者来讲Spring还不够简单优雅,运行的也不够快,所以才会尝试重新造这个大轮子,争取让应用系统的开发人员有更多的时间关注数据结构、业务逻辑和用户体验,也争取让小伙伴们有一个丝般顺滑的开发体验。

    边码代码边码文实属不易,作者需要您的支持请您多多点赞推荐!另欢迎感兴趣的小伙伴加入我们!

    下一篇:没有了