Java 能抵擋住 JavaScript 的進攻嗎?

JavaScript 的進攻

小編整理了一些java進階學習資料和麪試題,需要資料的請加JAVA高階學習Q羣:664389243 這是小編創建的java高階學習交流羣,加羣一起交流學習深造。羣裏也有小編整理的2019年最新最全的java高階學習資料!

公元 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 那樣,都是異步操作,只有一個主線程在忙活。” 線程大臣做了一個簡明扼要的彙報,不知道國王能否聽懂。

“衆位愛卿,你們說說該怎麼辦? 總不能讓這小小番邦屢次欺負我堂堂 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。

importio.vertx.core.AbstractVerticle;

publicclassServerextendsAbstractVerticle{

publicvoidstart(){

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 該怎麼寫? 查詢數據庫這麼慢,豈不是把事件循環都阻塞了?什麼事情都做不了了?”

“大人您忘了,我們這裏操作必須都是異步的,查詢數據庫也不例外。”

蒂姆說着展示了一段代碼, 通過異步的方式來查詢數據庫。

publicclassDatabaseVerticleextendsAbstractVerticle{

......

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進階學習資料和麪試題,需要資料的請加JAVA高階學習Q羣:664389243 這是小編創建的java高階學習交流羣,加羣一起交流學習深造。羣裏也有小編整理的2019年最新最全的java高階學習資料!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章