V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twogoods
V2EX  ›  程序员

关于异步编程

  •  
  •   twogoods · 2017-09-01 11:37:16 +08:00 · 3324 次点击
    这是一个创建于 2400 天前的主题,其中的信息可能已经有所发展或是发生改变。

    nodejs 这类异步为主导的程序里会出现 callback hell,这里我用 Java 写了一段 callback 嵌套的代码来类比 nodejs

    这里的三个嵌套是因为后一个依赖前一个的结果,那么这三个操作应该是不能并行的,所以 nodejs 写出了嵌套代码,那么问题是这种情况下异步式的代码不比同步的代码性能好吧?感觉业务上蛮多都是后一个依赖前一个,并行度并不高,引入异步编程会不会收益不大?

    client.getConnection(res -> {
                SQLConnection connection = res.result();
                connection.query("SELECT count(1) FROM T_User", res2 -> {
                    connection.query("SELECT count(1) FROM T_Book", res3 -> {
                        System.out.println(res2.result().getRows() + "--" + res3.result().getRows());
                    });
                });
            });
    

    同步写法

    SQLConnection connection=client.getConnection();
    data1=connection.query("SELECT count(1) FROM T_User");
    data2=connection.query("SELECT count(1) FROM T_Book");
    
    18 条回复    2017-09-01 22:30:54 +08:00
    Xrong
        1
    Xrong  
       2017-09-01 11:51:39 +08:00
    个人愚见:楼主的例子本身就看不出引入异步编程的好处,只是纯粹为了达到同步效果而不得以采用的写法而已。当然你可以用些 async 之类的库,假装看上去是同步的样子。
    jarlyyn
        2
    jarlyyn  
       2017-09-01 11:53:33 +08:00
    楼主需要了解 async 或者 promise

    还有 co 库。

    还是嫌麻烦不妨看看 go 之类的语言。
    keenwon
        3
    keenwon  
       2017-09-01 11:59:17 +08:00
    nodejs 是单线程,异步非阻塞的

    也就是说,三个嵌套的异步请求,有依赖关系,不是每有意义的,意义就在于第一个请求还未执行完的时候,线程空闲下来可以接受新的请求,或者继续执行其他同步代码,而不需要阻塞在哪里傻傻的等

    至于 callback hell,楼上说的 async/await,co 等都可以解决
    seki
        4
    seki  
       2017-09-01 12:01:44 +08:00
    前后依赖的本来就不是能并行的。可以并行的是你有多个不互相作用的任务的时候,可以一起执行
    twogoods
        5
    twogoods  
    OP
       2017-09-01 12:04:38 +08:00
    @keenwon 我是一个 Java 程序员,一直以来都是同步的方式写代码,Java 本身是多线程的 [线程空闲下来可以接受新的请求] 这个在 Java 里根本不是问题,所以我会有疑问,异步编程在 Java 里的适用场景
    a7063888
        6
    a7063888  
       2017-09-01 12:06:16 +08:00 via iPhone
    确实不大
    twogoods
        7
    twogoods  
    OP
       2017-09-01 12:07:54 +08:00
    @keenwon 再多问一句,你们 node 里 callback 嵌套或者说 async/await 这种用的多吗?用的多是不是也说明并行度不高,异步最大的好处体现的不多?
    chmlai
        8
    chmlai  
       2017-09-01 12:10:57 +08:00
    你整个系统又不是只有这个三个操作在跑.
    twogoods
        9
    twogoods  
    OP
       2017-09-01 12:19:19 +08:00 via Android
    @chmlai 所以问题是异步场景多吗?我本事接触的项目感觉不多
    gzlock
        10
    gzlock  
       2017-09-01 12:22:52 +08:00 via Android
    node 都 8 了还 hell 是多闭塞?鼻塞可以治疗,闭塞别人可帮不了你
    bazingaterry
        11
    bazingaterry  
       2017-09-01 12:23:08 +08:00 via iPhone
    @twogoods JS 天生就几乎没有阻塞的操作,网络请求大多都是异步进行的。
    keenwon
        12
    keenwon  
       2017-09-01 12:44:07 +08:00   ❤️ 1
    @twogoods

    1、用的多
    2、不是。单线程模型,异步的好处是很大的。

    在 node 主线程里,异步不代表并行,而是同一时间只做一件事,要么发起异步操作,要么执行异步操作的回调(有单独的线程检查异步是否执行完成,而且异步回调的执行只有等主线程空闲下来才行,所以 setTimeout 1ms 不一定是 1ms 后立刻执行)。并不是同时在做两件事,如果要真正的并行,可以启动子进程或者使用集群。

    所以 node,nignx 这样的东西,利用异步可以以极低的资源占用,处理大量的请求,不需要每请求每进程(线程)

    不知道我说清楚了没。写多了同步代码,可能一下子确实不太好理解 js 的异步。
    SuperMild
        13
    SuperMild  
       2017-09-01 12:56:00 +08:00 via iPhone
    网页需要非常强的容错能力,以便任何一步有问题,网页都不会卡住不动,所以 JS 天生异步。而 web server 是短时间内接受大量请求的典型场景,用单线程异步的语言可以轻易地提高效率,所以 node 的作者选择了 JS。可见,不是为了异步而异步,是有原因的。
    momocraft
        14
    momocraft  
       2017-09-01 13:01:56 +08:00   ❤️ 1
    并没有什么因素让异步自带性能好,js 那么多异步最初只是因为一线程的不得已。

    在这个比较中影响性能的不是 api 形式,是下面的 io 阻塞等因素。如果你把这份 java 代码写成 cps 变换那个样子,看上去就和异步 API 差不多,但是不要期待运行会变快。
    leonlu
        15
    leonlu  
       2017-09-01 13:07:31 +08:00
    LZ,现在你可以在 js 里边这么写了:

    let connection= await client.getConnection();
    data1=await connection.query("SELECT count(1) FROM T_User");
    data2=await connection.query("SELECT count(1) FROM T_Book");

    如果 data1 和 data2 没有啥前后依赖,你可以非常容易地做成并发 io:

    let connection= await client.getConnection();
    let [data1, data2] = await Promise.all([
    connection.query("SELECT count(1) FROM T_User"),
    connection.query("SELECT count(1) FROM T_Book")
    ]);

    是不是和 Java 一样好写了。。。
    aliuwr
        16
    aliuwr  
       2017-09-01 14:35:24 +08:00
    异步和并行是两个概念。
    autoxbc
        17
    autoxbc  
       2017-09-01 14:53:05 +08:00
    异步并不是一种处理问题的技巧或者方法
    而是一种对流程的更高层面的抽象

    世界模型本质是异步的

    描述世界的语言与这个模型越接近
    就越精确自然高效
    zhicheng
        18
    zhicheng  
       2017-09-01 22:30:54 +08:00
    异步是用来解决 IO Bound 类型的应用。无法解决 CPU Bound,甚至会多些一举。

    详细可以仔细看下我的文章。
    https://www.textarea.com/zhicheng/yong-python-lijie-fuwuqi-moxing-shang-566/
    https://www.textarea.com/zhicheng/yong-python-lijie-fuwuqi-moxing-xia-596/
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3215 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 12:00 · PVG 20:00 · LAX 05:00 · JFK 08:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.