• Java地位被撼动?Java与JavaScript的趣事连载


    第一回 JavaScript的进攻

    公元2014年,Java 第八代国王终于登上了王位。

    第一次早朝,国王坐在高高的宝座上,看着毕恭毕敬的大臣,第一次体会到了皇权的威力。

    德高望重的IO大臣颤悠悠地走上前来:“启禀陛下,昨日收到战报,有个叫做Node.js的番邦又一次向我国进攻,我边防将士死伤惨重。”

    “Node.js? 那是什么东西?” 国王心中一乐, 还真有人自不量力,想蚍蜉撼树。 想我Java帝国人口之众多,疆域之广阔,踩死你小番邦还不像踩死一只蚂蚁似的。

    “那是用JavaScript写的一个框架。” IO大臣看到国王不知道Node.js,心里一沉。

    “JavaScript? 爱卿说笑了,一个在浏览器中运行的东西,怎么可能进攻我Java后端。”

    “陛下有所不知,这JavaScript发展迅猛,不仅占领了前端,还通过Node.js向后端,尤其是我国渗透,臣还听说他们用Electron开始蚕食桌面开发了!”

    “竟有这等事!难道他们想通吃? 我们不是有Tomcat吗? 派Tomcat去把Node.js给镇压了。”

    国王开始怨恨自己的父亲JDK 7世和祖父JDK 6世没把这个Node.js当成一回事,没有把Node.js给扼杀在摇篮之中,把这个祸害留给了自己,心里开始发虚。

    第二回 非阻塞异步IO

    线程大臣走上前来:“陛下,Tomcat已经率军和Node.js恶战了几日,败下阵来, 这Node.js有个独门武器,叫做‘非阻塞异步IO’。”

    “非阻塞? 我听说我们的Tomcat也能实现非阻塞啊!” 王国有点惊讶。

    “不行的,陛下,Tomcat在处理连接的时候能实现非阻塞,但是在真正处理请求的时候还是需要同步操作,一个请求对应一个线程来处理,不像Node.js那样,都是异步操作,只有一个主线程在忙活。” 线程大臣做了一个简明扼要的汇报,不知道国王能否听懂。

    (码农翻身老刘注: Node.js的故事请参见《Node.js: 我只需要一个店小二》)

    “众位爱卿,你们说说该怎么办? 总不能让这小小番邦屡次欺负我堂堂Java帝国吧。”

    “臣倒是有一计,” 集合大臣说道,“这Node.js虽然来势汹汹,但是它也有个致命的缺点,那JavaScript是个动态语言,无法进行编译时类型检查,错误只有等到运行时才能暴露出来。用它开发个小项目还可以,一旦项目变大,代码变多,人员变多,那就会变成噩梦了。”

    “爱卿说说具体怎么办?”

    “我们可以派一些卧底去Node.js, 到处传播这样的消息,瓦解他们的军心和士气,让他们认为Node.js写的系统,很快就会腐化,最终还是要用我堂堂正正的Java语言来重写。”

    “嗯,此乃心理战也,至少会稳住一些墙头草,准奏,由爱卿来安排。 ” 国王说道,“不过,此法治标不治本,还是得想办法直接把他们打败。”

    “陛下真乃一代圣君,” 线程大臣马上开始拍马屁,与此同时,巧妙地把矛头转向老不死的IO大臣:“我Java帝国在第4代国王的时候就出现了非阻塞IO,这么多年过去了,居然还没发展出类似Node.js的系统,实在是不应该啊。”

    “老不死”的IO大臣是何等精明:“陛下明鉴, 我Java帝国应用服务器一直以来都是Tomcat独大,他们采用了线程池,每个请求一个线程的方式,我也不好干预。”

    IO大臣把责任推得一干二净。

    “没错,” 集合大臣为IO大臣打抱不平,两肋插刀,“还有一点就是这异步编程,听起来很好,但是写起来可就要命了,那么多的回调,简直就是反人类,臣民们戏称为回调地狱,没人愿意那么写,发展不起来也很正常。”

    线程大臣马上接口:“此言差矣,陛下已经教会了臣民们如何使用Lambda表达式,并且现在也出现了RxJava,已经没什么回调地狱了!”

    “那是现在,以前可没有!”

    “......”

    国王看到这几位大臣要打起来,马上施展和稀泥之术:“众位爱卿各有道理,你们且说说,怎么才能打败着来势汹汹的Node.js吧。”

    没人说话。

    国王只好退朝。

    第三回 京城酒馆

    京城的小酒馆向来是一个多方消息的集散地。

    一个金发碧眼的小伙子正在“危言耸听”:“听说了没有,Node.js又赢了几仗,Tomcat大军死伤惨重,有不少臣民都投奔到那个番邦去了。”

    “这异步操作真的有这么厉害?” 有人问道。

    小伙子喝了一口酒: “其实不是异步操作更好,而是在高并发的环境异步操作更有效,大家都知道, 一个机器能支持的线程数目是有限的,不可能一直增加。Tomcat那种一个请求一个线程的方式很快就会遇到瓶颈。”

    “你说说,到底有什么好处?”有人刨根问底。

    “现在服务器端的操作无非就是操作文件,读写数据库,访问远程服务,这些都是所谓阻塞操作。” 小伙子展开了一张图:

     

     

    “橙色的都是IO操作,绿色的才是真正的线程执行, IO操作非常耗时,线程大部分时间都浪费在了等待上面! 如果能让线程不要等待,去做别的事情,那用少量的线程,甚至一个线程就可以了。”

    众人纷纷点头, 这小伙子已经看出了问题的关键,现在的很多系统,都是IO密集的, 高并发情况下,如果一个请求一个线程,浪费巨大。

    “想我Java 虚拟机如此强悍,如果能实现异步操作,那还不把Node.js秒成渣?!”小伙子狠狠地用手锤了一下桌子。

    正在此时,酒馆冲进一队士兵,赶走众人,围住小伙子,领头的喝问到:“大胆刁民,竟然到处宣扬异步思想,给我带走!”

    士兵恶狠狠地把他五花大绑,推出门去, 留下一堆人在那里议论纷纷。

    第四回  IO王府

    “我让你们把他请来,怎么绑来了?快松绑!” IO大臣呵斥完下属,转头亲切地问道:“叫什么名字啊?”

    “小人蒂姆, Tomcat府上的幕僚。 ” 蒂姆一边说一边揉肩膀。

    “Tomcat府上的人......” IO大臣捻着胡须若有所思。

    “是的,大人,我还见过您呢,您上次半夜去Tomcat府上密谈......”

    “住口! ” IO大臣赶紧转换话题, “我的下属发现你到处宣扬异步思想,究竟要干什么? ”

    “小人发明了一个系统,叫做Node.x。 ”

    “为什么不献于Tomcat 将军?”

    “唉,小人进言多次,可是将军不听啊!”

    “你说说看,这是个什么东西? 是要模仿Node.js吗?” IO大臣问道。

    之前蒂姆给Tomcat将军讲述过Node.js, 他理都不理,经常是一甩袖子就走, 自己是空有一身本领却无人赏识, 难道这IO大臣能帮自己一把? 想到此处,蒂姆精神大振。

    “确实受到了它的启发, 但是我的Node.x在架构和一些关键的抽象上和Node.js有很大不同。” 蒂姆不好意思地笑了笑,“先说说相同的部分,既然都是异步操作,那肯定是通过事件驱动的,所以都有一个事件循环。”

     

     

    IO大臣之前和Swing大臣聊过, 知道事件循环是怎么回事,这是一个相当古老的概念了。

    无非就是有个线程在检测一个队列,如果队列中有事件,就拿出来处理。

    “只不过我这里有所不同,可以创建多个事件循环出来,比如每一个CPU核心有一个,这样可以充分利用CPU的多核性能。” 蒂姆得意地说道。

    (4个CPU core, 4个事件循环)

    IO大臣点头表示赞许, 他听说Node.js好像只有一个主线程,没法直接利用多核的能力。想利用多核的话还得开多个进程才行。

    第五回 异步操作

    “你图中的那个Hanlder就是具体的业务代码所在地吧? 具体长什么样子啊,让我看看!” IO大臣问道。

    蒂姆赶紧呈上代码,这是简单的Hello World。

    import io.vertx.core.AbstractVerticle;

    public class Server extends AbstractVerticle {

      public void start() {

        vertx.createHttpServer().requestHandler(req -> {

          req.response()

            .putHeader("content-type", "text/plain")

            .end("Hello Word!");

        }).listen(8080);

      }

    }

    这段代码生成了一个简单的HTTP 服务器, 在8080端口监听, 每当有请求来的时候,都返回一个字符串“Hello World!”。

    IO大臣一看,大为吃惊:“你这代码不需要外部容器,自己就搞了一个HTTP服务器啊?”

    “是的,这样我们就完全不用Tomcat了。 我把这种类起来一个名称,叫做Verticle, 部署以后,这个Verticle就可以和一个事件循环关联了。每次有HTTP请求过来,Node.x会封装成事件,然后分派给它处理了。”

    真是个二愣子, IO大臣心想, 怪不得Tomcat对你不待见,你这个东西出来,他的位置不保啊!

    IO大臣问道:“那对于数据库查询,你这个Handler,哦不,Verticle该怎么写? 查询数据库这么慢,岂不是把事件循环都阻塞了?什么事情都做不了了?”

    “大人您忘了,我们这里操作必须都是异步的,查询数据库也不例外。”

    蒂姆说着展示了一段代码, 通过异步的方式来查询数据库。

    public class DatabaseVerticle extends AbstractVerticle{

        ......

        dbClient.getConnection(ar -> {

            if (ar.succeeded()) {

                SQLConnection connection = ar.result();

                connection.query("select .. from...", res -> {      

                     if (res.succeeded()) {

                       ......

                     } else {

                       ......

                     }

              });

            } else {

               ......

            }

        });

    }

    IO大臣感慨道:“唉,老了,真是不中用了,连异步都忘了。对了,这些个Verticle看起来都是独立的,是被不同的线程调用的,他们之间怎么进行交互啊?难道也通过共享内存的方式?”

    “大人真是厉害,一下子就问到了核心问题,不能让他们共享内存,那样就需要加锁了,我这里引入了Event Bus的方法,让他们之间通过消息传递。”

     

    “嗯,不错,实现了低耦合。”

    “不仅如此,这些Verticle还可以部署到不同的JVM中,通过Event Bus实现真正的分布式通信。” 蒂姆又抛出一个重磅炸弹。

    “如此甚好!” IO大臣爱才之心骤起, “你愿不愿意到老夫府上做幕僚啊?”

    “小人愿意追随大人!”

    “好!明日早朝,你随我入宫,面见圣上,老夫保你一世荣华富贵。 ”

    第六回 为什么是Vert.x?

    第二日早朝,IO大臣迫不及待地给国王报喜:“陛下,我Java 帝国也可以采用非阻塞异步编程了!击败Node.js之日可待。”

    IO大臣讲述了昨晚的情况, 细数了Node.x的种种好处。

    Tomcat将军脸上极为难看, 赶紧阻止:“陛下不可,我Java帝国采用同步处理已经很久了,臣民们已经习惯了,现在改成异步,怕激起民变。”

    “爱卿不要低估臣民采用新技术的能力嘛, 宣蒂姆进殿,呈上代码。”

    蒂姆都不敢看Tomcat, 从怀里掏出一张纸,双手奉上。

    vertx.createHttpServer()

      .requestHandler(function (req) {

        req.response()

          .putHeader("content-type", "text/plain")

          .end("Hello World");

    }).listen(8080);

    国王盯着看了半天:“嗯?不对啊,你这不是Java代码吧?”

    Tomcat拿过国王递过来的代码,扫了一眼:““大胆! 你竟然敢在朝堂之上公然宣传JavaScript,来人,拿下!”  

    “陛下息怒,这是小人制定的一个策略,我的Node.x支持很多语言编程, 除了Java之外,还有JavaScript,Ruby, Scala, Kotlin等等。”

    “哦? 是吗? 这还能把番邦的人给吸引过来呢!你说呢,Tomcat将军?” 国王说道。

    Tomcat有些不自在,想找回场子:“嗯嗯,有一定道理,不过这个Node.x这个名字不好,拾人牙慧,让人看低我堂堂Java帝国。” 

    “Node是节点的意思,朕把他改成vertex如何?也是节点的意思。”

    “ 陛下圣明,可否叫做vert.x ? ” IO大臣提议。

    “好,准奏,即日起,命你和蒂姆训练臣民使用vert.x,一个月后向Node.js开战!” 国王已经忍Node.js很久了。

    不,不能让IO大臣的Vert.x一家独大! 

    国王突然想到了亲爹留下来的祖训, 帝王之术是一定要平衡朝局。

    “吩咐下去,今晚朕要和Spring将军,嗯,还有线程大臣,共进晚餐,朕有些事情要和他们好好谈谈......”

    (本文来自 码农翻身 刘欣)上海尚学堂Java培训shsxt.com

  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/shsxt/p/10373720.html
Copyright © 2020-2023  润新知