第一回 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

Java地位被撼动?Java与JavaScript的趣事连载的更多相关文章

  1. 基于类(Java)和基于原理(JavaScript)的对象系统的比较

    Java:面向对象编程语言,吸收了C++语言的各种优点,丢掉了C++让人头疼的多继承.指针等概念.具有功能强大和简单易用的两大特征.Java具有简单性.面向对象.分布式.健壮性.安全性.平台独立与可移 ...

  2. 用JAVA编写浏览器内核之实现javascript的document对象与内置方法

    原创文章.转载请注明. 阅读本文之前,您须要对浏览器怎样载入javascript有一定了解. 当然,对java与javascript本身也须要了解. 本文首先介绍浏览器载入并执行javascript的 ...

  3. (转)如何学习Java技术?谈Java学习之路

    51CTO编者注:这篇文章已经是有数年“网龄”的老文,不过在今天看来仍然经典.如何学习Java?本篇文章可以说也是面对编程初学者的一篇指导文章,其中对于如何学习Java的步骤的介绍,很多也适用于开发领 ...

  4. Java 新特性(5) - Java EE 5 新特性

    Java EE 5 由 Java Community Process 通过 Java Specification Request 244 发布,这个 “总纲” JSR 指出了详细描述 Java EE ...

  5. java各种概念 Core Java总结

    Base: OOA是什么?OOD是什么?OOP是什么?{ oo(object-oriented):基于对象概念,以对象为中心,以类和继承为构造机制,来认识,理解,刻画客观世界和设计,构建相应的软件系统 ...

  6. java数组遍历、java方法定义

    1.遍历数组for与foreach String [] test =  {"java","php","bootstrap","vu ...

  7. java基础(十二 )-----Java泛型详解

    本文对java的泛型的概念和使用做了详尽的介绍. 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即“参数化类型”.一提到 ...

  8. Java基础学习(一)---Java初识

    一.Java介绍 关于Java的诞生和发展网上比较多,在此就不再赘述了,可以参考http://i.cnblogs.com/EditArticles.aspx?postid=4050233. 1.1 J ...

  9. 【Java】-NO.11.Java.1.Log4j.1.001-【Log4j Manual】-

    1.0.0 Summary Tittle:[Java]-NO.11.Java.1.Log4j.1.001-[Log4j2 Manual]- Style:Java Series:Log4j Since: ...

随机推荐

  1. 计算两个latitude-longitude点之间的距离? (Haversine公式)

    问题描述 如何计算纬度和经度指定的两点之间的距离?为了澄清,我想要距离公里;这些点使用WGS84系统,我想了解可用方法的相对准确性.最佳解决方案 这个link可能对您有帮助,因为它详细说明了使用Hav ...

  2. Android 手势检测实战 打造支持缩放平移的图片预览效果(下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39480503,本文出自:[张鸿洋的博客] 上一篇已经带大家实现了自由的放大缩小图 ...

  3. python selenium模拟滑动操作

    selenium.webdriver提供了所有WebDriver的实现,目前支持FireFox.phantomjs.Chrome.Ie和Remote quit()方法会退出浏览器,而close()方法 ...

  4. Immutable(不可变)集合

    Immutable(不可变)集合 不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对 ...

  5. hibernate MTM 联合主键

    //适用于表里没有其他列,只有主键 //Course.java实体类 package com.tao.pojo; import java.util.HashSet; import java.util. ...

  6. 关于MySQL死锁

    最近项目中遇到一个问题,使用Spring事务嵌套时,导致MySQL死锁.记录一下,时刻提醒自己. 场景如下, 事务嵌套, 最外层有默认事务, 嵌套一个独立事务, 独立事务和外部事务同时操作一张表.

  7. [Usaco2015 Jan]Grass Cownoisseur 图论 tarjan spfa

    先缩点,对于缩点后的DAG,正反跑spfa,枚举每条边进行翻转即可 #include<cstdio> #include<cstring> #include<iostrea ...

  8. CSS 盒模型与box-sizing

    一.盒模型 一个web页面由许多html元素组成,而每一个html元素都可以表示为一个矩形的盒子,CSS盒模型正是描述这些矩形盒子的存在. MDN的描述: When laying out a docu ...

  9. C# Vista Command Link Control with Windows Forms

    using System; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; u ...

  10. 基于Orangpi Zero和Linux ALSA实现WIFI无线音箱(三)

    作品已经完成,先上源码: https://files.cnblogs.com/files/qzrzq1/WIFISpeaker.zip 全文包含三篇,这是第三篇,主要讲述接收端程序的原理和过程. 第一 ...