整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Java 能抵挡住 JavaScript 的进攻吗?

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 将军,嗯,还有线程大臣,共进晚餐,朕有些事情要和他们好好谈谈......”

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

声明:作者独立观点,不代表 CSDN 立场。

下讨论只针对PC端和移动端。

Java最大的优势真的在于跨平台吗?

以前是,但现在已经不是了。

有跨平台需求的仅仅是客户端应用,而不是服务端。例如桌面应用,你的客户可能是Windows用户,也可能是Linux用户,这时候如果不想多投入成本对各个平台进行适配,那么Java所谓的“Write once, run everywhere”就显得异常光彩。然而今天,整个软件世界都在向B/S应用倾倒(嵌入式除外),即使要做客户端跨平台,QT等第三方框架远远比Swing更强大,Java在桌面应用领域基本被淘汰已经是不争的事实了,而当初Java引以为豪的Applet也早已销声匿迹。如果说客户端Java还有一点优秀的话,那只有Android了。安卓最初确实靠JVM屏蔽了不同硬件设备之间的区别并取得了巨大的成功,但在今天,Android L中ART模式的出现也即将颠覆这一情况,况且Google还可能会想用自家的Go语言取代Java成为Android平台的第一语言。所以在客户端,Java几乎完败

服务端应用不需要跨平台。做一个Web服务器,我想没有哪家公司今天用Linux,下个月就换Windows吧?如果仅仅是更换Linux发行版,如从Debian到Fedora,本质上讲其Linux内核是不变的,因此像C++这样纯编译类型的语言已经没什么问题。如果做游戏服务器,我想几乎都会选择Linux而不是Win平台。Java的跨平台优势的实用性其实已经被大大弱化了,可以说在实际应用中并不明显,在一般情况下几乎感知不出Java还能跨平台这个特性。作为三大商用JVM之一的JRockets是只有编译器的JVM,即应用启动时会将字节码全部编译为本地机器码,这其实就很大程度上摒弃了跨平台,而追求性能。

今天,Java最大的优势在于其庞大而完善的生态系统。一门编程语言是否能流行,主要是由其生态系统决定的。Java生态系统的完善性主要体现在以下几个方面:

Java拥有世界上数量最多的程序员。你说他们是农民也好,但数量放在那里,最明显的效果就是公司招人的时候会比较容易地招到Java程序员。试想如果你想要做一套软件,你有一个很棒的技术方案需要用C++,Scala或Ruby等语言实现,但招不到足够的人手,那么计划多半泡汤。这时候你的应用Java也能做到,并且很轻松就能招到足够的人,那么你选择Java的可能性就要大一些。

Java拥有大量的第三方类库。假如你想解析HTML,用C/C++这类语言恐怕多半只能自己编写解析算法库了,而如果是Java,你可以非常轻松地在Github上找到JSoup,使用Maven导入依赖后分分钟就搞定HTML。为此还有一句讽刺Java的话是:“我们不生产代码,我们只是Github的搬运工。”这句话从字面上看是很有道理的,但却忽略了对软件生产效率的提升所带来的巨大价值。对于软件的开发,公司的唯一成本其实就是“人头费”,每减少一个月开发时间,就能帮助公司节省几十万几千万的研发成本。

Java拥有功能强大的IDE。Eclipse,通过插件几乎可以满足你开发的任何需求。它虽然有些慢,但你可以通过JVM调优来提高程序的流畅度,千万不要使用默认的JVM参数。不过,IntelliJ Idea已经完全超越Eclipse了,Idea的智能程度几乎可以媲美Win平台下的VS。我是那类离了Vim就活不下去的人,在这两款IDE中都有Vim插件从而让我愉快地存活下去。

Java拥有很多杀手级应用。不必多说,Spring, Struts, Hibernate, Hadoop, Tomcat, JBoss等等。

Java的语法特性很少。对,这也是一项优点。C++相比C添加了大量特性,学起来费事不说,用起来还会降低代码可读性,其实是费了工夫不讨好。当今世界对编程语言的要求是语法简单,代码可读,对性能已经是退而求其次了,因此才诞生了Python, Ruby这样的编程语言。有很多人批评Java语法写起来很臃肿,我承认这一点,但事实是,编程语言从来都不是因为语法臃肿而被淘汰的,决定其生死的是生态系统。对于批评者,引用知乎的一句话:“动态类型一时爽,代码重构火葬场”

Java的性能已经足够高了。Sun/Oracle的HotSpot JVM内置的JIT编译器在运行时对字节码已经做出了非常大的优化努力,服务端应用启动后对JVM进行足够的“预热”,并给出合理的启动参数即可。如果不是对性能十分敏感的系统类应用,Java已经足够快了。有一种简单可行的方法可以形象地看出这点,在JVM启动参数中添加+XX:PrintCompilation可以看到JIT编译器的忙碌。当今世界对软件的需求量越来越大,在性能可接受的情况下,开发效率才是第一位的,这也是Python这类动态脚本语言流行的主要原因。

以上仅做客观分析,并不想引起语言战争。毕竟,没有最好的语言,只有最适合某种项目的语言。引用黑格尔的一句话:“存在即合理。”

者 | Yanique Andre

译者 | Arvin,责编 | 屠敏

头图 | CSDN 下载自东方 IC

出品 | CSDN(ID:CSDNnews)

以下为译文:

JavaScript被淘汰了吗?

我在许多不同的网站(最近是在Quora)上多次阅读到这个问题,我一直在想这是不是真的。我在2018年才开始web开发,所以我不了解JavaScript的历史,也不了解它在开发领域的现状。

因此,我进行了一些研究去了解JavaScript的过去和现在,我发现的结果相当令人震惊。

我们曾经认识的JavaScript确实已经死了。

自1995年首次建立JavaScript以来,JavaScript一直存在很多问题。尽管进行了一些更新,但许多主要问题仍然没有得到解决。

JavaScript的一些问题包括:

  • 缺少模块系统

  • 弱类型

  • 高度依赖全局变量

  • 由于语法的原因很难找到错误

在过去的十年中,用该语言很难创建框架。AngularJS最初是基于JavaScript的框架,直到遇到扩展框架的问题,所以他们决定使用TypeScript(JavaScript的一种变体)重新编码整个框架,并将其重命名为Angular。

人们对JavaScript的兴趣似乎也在下降。通过查看过去5年“JavaScript”一词在google上的搜索频度,似乎也能看到这门语言正在慢慢走向衰落。

这意味着什么呢?JavaScript真的要死了吗?

我当时也这么想。当我在2018年第一次学习JavaScript时,JavaScript已扩展为不仅仅面向客户端应用程序,已经扩展出许多涉及应用程序不同周期的框架。

基于js的框架包括下面这些:

  • 前端应用程序(Angular,React,Vue.js)

  • 后端应用程序(Node.js,Express.js,Meteor.js)

  • Android / iOS(React Native,NativeScript,Ionic)

  • 机器学习(TensorFlow)

您可以在这里找到JavaScript库的完整列表:https://en.wikipedia.org/wiki/List_of_JavaScript_libraries

上面列表中的大部分JavaScript库是在过去10年中创建的。这些库有很多社区支持,并保持步调一致的更新(Angular平均每6个月更新一次)。开发人员对这些库进行了大量修改(尤其是前端框架),并在保持JavaScript的相关性方面发挥了巨大作用。

这也可以解释为什么上面显示的谷歌趋势图是向下的。对术语“JavaScript”的实际搜索呈下降趋势,但对JavaScript库的搜索呈上升趋势。

随着JavaScript库的兴起,也有越来越多的用户提出与这些库有关的问题。StackOverflow趋势记录了他们的问题与某个标签相关的百分比。看看在过去的十年中有多少关于JavaScript的问题:

这解决了涉及JavaScript的问题,

但是否解决了这门语言本身的问题呢?

多年来,人们对JavaScript的抱怨主要集中在其糟糕的语言特性上。值得庆幸的是,我们正在看到一个旧标准的复苏,这有助于使语言更加具体和有效。

ECMAScript是一种编程语言,根据Ecma International创建的ECMA-262文档进行标准化。该文档包含JavaScript作为编程语言必须遵循的标准列表。

ECMAScript创建于1997年,从1997年到2011年仅进行了5次更新。这使JavaScript在21世纪的前十年一直保持着陈旧和过时的标准。直到2015年ECMAScript 6发行,这是对JavaScript的重大更改,允许许多类似的库对其进行修改。

自此ECMAScript已发布了5个版本,从2015年到2020年每年发布1个版本,并且现在还没有停止。随着发布版本步调的一致性,JavaScript开始不断接收更新,变得更加健壮、高效,并且适应性更强。

说了这么多,JavaScript真的死了吗?

有些人会怀疑现在开始学习是否为时已晚。正确的答案是JavaScript从未像现在这样活跃。

随着对该语言的贡献和支持达到前所未有的高度,学习该语言对开发者来说将是一笔巨大的财富。因为有如此多的库可以选择,你可以只使用JavaScript框架组成整个堆栈。

要求开发人员具有React和Angular经验的公司数量正在大幅增加,并且没有放缓的趋势。

我建议你花些时间学习JavaScript。无论你打算从事该行业还是只是想学习它,我认为将来需要在应用程序中使用JavaScript的地方有很多。该语言将被用在越来越多的框架中。它是未来的趋势,而且发展得很快。

原文:https://medium.com/dev-genius/is-javascript-development-dying-1dbce0094fc0

本文为 CSDN 翻译,转载请注明来源出处。