Java 能抵挡住 JavaScript 的进攻吗?

JavaScript 的进攻

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

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

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

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

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

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

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

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

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

非阻塞异步 IO

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

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

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

注: Node.js的故事请参见《Node.js: 我只需要一个店小二》

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

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

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

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

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

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

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

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

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

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

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

“......”

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

没人说话。

国王只好退朝。

京城酒馆

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

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

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

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

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

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

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

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

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

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

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

IO 王府

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

“小人蒂姆, 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 该怎么写? 查询数据库这么慢,岂不是把事件循环都阻塞了?什么事情都做不了了?”

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

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

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 的方法,让他们之间通过消息传递?!?/p>

“嗯,不错,实现了低耦合?!?/p>

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

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

“小人愿意追随大人!”

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

为什么是 Vert.x?

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

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

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

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

蒂姆都不敢看 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 等等?!?/p>

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

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

“Node 是节点的意思,朕把他改成 Vertex 如何?也是节点的意思?!?/p>

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

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

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

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

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

*本故事纯属虚构,如有雷同,纯属巧合。

声明:作者独立观点,不代表 从开始到以后 立场。

?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容