面試官:你知道協程嗎?
你:訂機票的那個嗎,我常用。
面試官:行,你先回去吧,到時候電話聯系
。。。。。。。。
很尷尬,但是事實是,很大一部分的程序員不知道協程是啥玩意,更大一部分的程序員,項目中沒用到協程。
先介紹下協程吧。
計算機有進程,線程和協程。前兩者大家都知道,很常見的玩意。而協程,則是基於線程之上的,自主開辟的異步任務,很多人更喜歡叫它們纖程(Fiber),或者綠色線程(GreenThread)。
協程的特點:
- 線程的切換由操作系統負責調度,協程由用戶自己進行調度,因此減少了上下文切換。
- 線程的默認Stack大小是1M,而協程更輕量,接近1K。因此可以在相同的內存中開啟更多的協程。
- 由於在同一個線程上,因此可以避免競爭關系而使用鎖。
為什么我會說到協程,這個很多java程序員都沒用過的東西。第一、吸引眼球!

好了,言歸正傳。
是springboot2.0 webflux發布之后,很多人大呼精彩,開始各種比較他與傳統selvet性能高低。其實不然,webflux的模式其實和servlet3的模式殊途榮歸,都是屬於線程委派模式,將業務線程丟給另外的線程池處理來達到業務異步的效果。這樣的確能提高某些情況下的吞吐量,但是卻不是能達到的理想狀態。
為什么這么說,因為我們假如業務線程池設置的最大線程數是1000,那么在核心線程數處理不過來的時候,就會不斷的新增線程數直到1000,這樣系統中就會出現大量的上下文切換而導致性能損耗。
這里補充一下:CPU線程數代表能同時處理多少線程任務,至於多出來的線程任務,則是CPU根據時間片或阻塞狀態不斷切換線程來執行,而切換線程的時候,則需要保存當前線程的狀態,和恢復要切換的線程狀態,這種對性能損耗很大的。
上下文切換的規則是一個線程運行超過5ms,或者出現阻塞,比如IO操作。
而一般像我們CURD程序員的業務操作離不開大量的IO操作(數據庫讀寫),因此,將業務丟在一個線程池中,輪到CPU給你時間片的時候,你立馬就告訴CPU:走吧走吧,我還在阻塞呢。 然后讓線程立馬就切換,可想而知這不是一個理想的操作。同時隨着線程的增大,你的內存也不斷在增大。
那么這個時候我們該如何處理呢?協程,對了~
協程是怎么來處理的呢,就是對於一個阻塞的業務操作,我們不是用線程來處理,而是用用協程,這樣當出現IO阻塞的時候,並且你還沒運行完時間片,你不會讓CPU跑掉,而是調起你的另一個協程任務,讓他繼續進行計算。而通常我們知道,代碼純計算執行是非常快的,5ms可能跑了N個方法了,因此這樣充分的利用時間片,並且減少CPU切換的時間。
其實在go,以及kotlin中,早已原生支持了協程的概念,所以go以及kotlin的ITer會相對javaer更多的了解協程。
此時javaer欲哭無淚啊。
但是我們真的就不能用協程了嗎?雖然java官方還未支持,但是確有第三方支持的,下面給大家介紹下。
Quasar
一個比較成熟的java三方協程庫,熟悉之后可用於生產環境。
Alibaba Dragonwell
阿里巴巴開源的發行版jdk,老爸是阿里內部的ajdk,但是目前ajdk的協程還沒繼承過來,說法是在慢慢繼承。
Project Loom
oracle的jvm級項目,重新實現線程模型,里面包含協程方案,目前Quasar作者已經加入。(oracle忙着發JDK呢,這個還在無限延期)
kotlin
kotlin原生支持攜程,且也是基於jvm運行的語言並且可以相互調用,可以考慮相互協作。
好了,說了這么多,其實就是一句話,目前現成的像樣點的純種協程框架就只有quasar,混種的就用kotlin吧。至於quasar,會在后續文章中繼續介紹。