314
技術社區[雲棲]
從JAVA多線程理解到集群分布式和網絡設計的淺析
由於最近工作原因,很久沒有在CSDN上留下些啥,今天在這些篇文章,是關於java多線程的。
對於JAVA多線程的應用非常廣泛,現在的係統沒有多線程幾乎什麼也做不了,很多時候我們在何種場合如何應用多線程成為一種首先需要選擇的問題,另外關於java多線程的知識也是非常的多,本文中先介紹和說明一些常用的,在後續文章中如果有必要再說明更加複雜的吧,本文主要說明多線程的一下幾個內容:
1、在應用開發中什麼時候選擇多線程?
2、多線程應該注意些什麼?
3、狀態轉換控製,如何解決死鎖?
4、如何設計一個具有可擴展性的多線程處理器?
5、多線程聯想:在多主機下的擴展-集群?
6、WEB應用的多線程以及長連接原理。
1、在應用開發中什麼時候選擇多線程。
在前序的文章中已經簡單提及到過一些關於多線程應用的文章,通過對web的一些線程控製對下載流量的控製,其實那隻是雕蟲小技,也存在很多的問題需要去解決,不過麵對用戶量不大的人群一般問題不大而已。
多線程在生活中的體現就是將多個同樣很多事情交給多個人來並行的完成,而中間有一個主線程起到調度者的作用,運行者可以強製依賴於主線程的存在而存在,也可以讓主線程依賴於自身;曾經我聽很多人說過如果你的機器是單CPU,多線程沒有意義,其實我並不這麼認為,以為內單個CPU隻能證明在線程被調度的瞬間隻能同時執行一條最底層的命令,而並不代表不可以在CPU的征用上提高效率,一個是內存級別的,而另一個是CPU級別的,效率上仍然存在很大差距的;(這個可以讓一個程序單線程去循環10億次(每次自增1),和讓十個線程獨立運行1億次也是同樣的動作,記住這裏不要將每條數據System.out.println出來,一個是機器扛不住,另一個是這裏會對測試數據產生影響,因為這個方法我前麵的文章中已經說明會產生阻塞,尤其是在並發情況下的阻塞,即使在單CPU下結果肯定也是有很大差距的,我這暫時沒有單核的PC機器,所以沒法得到一些測試結果數據給大家,請有條件的朋友自己測試一下)。
在現在的係統中無時無刻都離不開多線程的思想,包括集群、分布式都可以理解為多線程的一種原理,那麼什麼是多線程的原理呢?多線程和多進程的是什麼呢?
其實要實現分布最簡單的思想就是多進程,其實類似於在係統分隔過程中的一種垂直分隔,將不同業務的係統分布在不同的節點上運行,他們彼此互不幹擾,而多進程的申請、釋放資源各方麵的開銷都很大,而且占用資源並非CPU級別的,而線程是屬於進程內部更細節的內容,一個進程內部可以分配N個線程,這些線程會並行的征用CPU資源,如果你的機器是多核的處理器,並發將會帶來異常的性能提升,其實原理上就是在有限的資源下,如何發揮出最大的性能優勢(但是一定是資源有一定餘量的情況下,正所謂做事不能做得太絕)。
在java中常用於實現多線程的方法有3中:
1、繼承於Thread類,重寫run方法
2、實現Runable接口,實現run方法
3、實現Callable接口,實現call方法(具有返回值)
至於調用的方法多種多樣,可以直接用start啟動,也可以使用java.util.concurrent.Executors來創建線程池來完成,創建的線程池也主要分為:
1、Executors.newSingleThreadScheduledExecutor() 創建一個順序執行的線程池,你在run方法內部無需使用synchronized來同步,因為它本身是順序的。
2、Executors.newCachedThreadPool()創建一個線程池,線程會並行的去執行它。
3、Executors.newFixedThreadPool(10)創建大小為10的一個線程池,這個線程池最多創建長度為10的隊列,如果超過10個,就最多有10個線程在執行,即可以控製線程的數量,也可以讓其並行執行。
如果你的係統是一個WEB應用,建議盡量不要再web應用中做多線程,因為這部分線程控製主要是由web容器控製的,如果在非得必要的情況下建立,盡量建立較少,或者盡量將可以不太頻繁調度的線程使用完後直接釋放掉,哪怕下次重建也無所謂。
如果你的多線程序是獨立運行的,專門用於接受和和處理一些消息,那麼我相信最少有一個線程是不斷探測的(有很多程序會先休眠一點時間,如:TimeUnit.MINUTES.sleep(SLEEP_TIME)此方法是按照毫秒級進行休眠一段時間),這類程序,最好將線程設置為後台線程(setDaemon(true),一定要在線程調用run之前調用該方法有效),後台線程和非後台線程最大的區別在於:後台線程在所有非後台線程死掉後,後台線程自動會被殺死和回收;而正如你寫其他的多線程程序,即使你的main方法完成(主線程),但是在main中申請的子線程沒有完成,程序仍然不會結束。
總的來說,其實幾乎每時每刻寫的代碼都是多線程的,隻是很多事情容器幫助我們完成了,即使編寫本地的AWT、SWING,也在很多控製處理中式異步的,隻是這種異步相對較少,更多的異步可以由程序去編寫,自定義的多線程一般用於在獨立於前段容器應用的後台處理中。為什麼類似web應用的前端會把多線程早就處理好呢,一個是因為為了減少程序和bug,另外一個就是要寫好多線程的確不容易,這樣會使得程序員去關心更多沒有必要關心的東西,也需要程序員擁有很高的水準,但是如果要成為好的程序員就一定要懂多線程,我們接下來以幾個問題入手,再進行說明:
如果一個係統專門用於時鍾處理、觸發器處理,這個係統可能是分布式的,那麼在一個係統內部應該如何編寫呢?另外多線程中編寫的過程中我們最鬱悶的事情、也是最難琢磨補丁的是什麼:多線程現在的運行狀況是怎樣的?我的這個線程不能死掉,如果死掉了我怎麼發現?發現到了如何處理(自動、人工、難道重啟)?
帶著這些問題,我們引出了文章下麵的一些話題。
2、多線程應該注意些什麼?
多線程用起來爽,出現問題你就不是那麼爽了,簡單說來,多線程你最納悶的就是它的問題;但是不要害怕它,你害怕它就永遠不能征服它,嗬嗬,隻要摸清楚一些脾氣,我們總有辦法征服它的。
◆明白多線程有狀態信息,和之間的轉換規則?
◆多線程一般在什麼情況下會出現焊住或者死掉的現象?
◆多線程焊住或者死掉如何捕獲和處理?
這裏僅僅是提出問題,提出問題後,在說到問題之前,先提及一下擴展知識點,下麵的章節來說明這些問題。
開源多線程調度任務框架中的一個很好選擇是:Quartz,有關它的文章可以到https://wenku.baidu.com/view/3220792eb4daa58da0114a01.html
下載這個文檔,這個文檔也講述了大部分該框架的使用方法,不過由於該框架本身的封裝層次較多,所以很多底層的實現內容並不是那麼明顯,而且對於線程池的管理基本是透明的,自己隻能通過一些其他的手段得到這些內容。
所以拿到這個框架首先學習好它的特性後,進一步就是看如何進一步封裝它得到最適合你項目的內容。
另外多線程在數據結構選項上也有很多技巧,關於多線程並發資源共享上的數據結構選型專門來和大家探討,因為技巧的確很多,尤其是jdk 1.6以後提出了很多的數據結構,它參考了類似於oracle的版本號原理,在內存中做了數據複製以及原子拷貝的方法,實現了即保證一致性讀寫又在很大程度上降低了並發的征用;另外還有對於樂觀鎖機製,也是高性能的多線程設計中非常重要知識體係。
3、狀態轉換控製,如何解決死鎖。
3.1.java默認線程的狀態有哪些?(所謂默認線程就是自己沒有重寫)
NEW :剛剛創建的線程,什麼也沒有做,也就是還沒有使用start命令啟動的線程。
BLOCKED :阻塞或者叫梗阻,也就是線程此時由於鎖或者某些網絡原因造成阻塞,有焊住的跡象。
WAITING:等待鎖狀態,它在等待對一個資源的notify,即資源的一個鎖機會,這個狀態一般和一個靜態資源綁定,並在使用中有synchronzed關鍵字的包裝,當使用obj.wait()方法時,當前線程就會等待obj對象上的一個notify方法,這個對象可能是this,如果是this的話那麼在方法體上麵一般就會有一個synchronized關鍵字。
TIME_WAITDE:基於時間的等待,當線程使用了sleep命令後,就會處於時間等待狀態,時間到的時候,恢複到running狀態。
RUNNING:運行狀態,即線程正在處於運行之中(當線程被梗阻)。
TERMINATED:線程已經完成,此時線程的isAlive()返回為false。
一般默認的線程狀態就是這些,部分容器或者框架會把線程的狀態等進行進一步的封裝操作,線程的名稱和狀態的內容會有很多的變化,不過隻要找好對應的原理也不會脫離於這個本質。
3.1.線程一般在什麼情況下會死掉?
鎖,相互交叉派對,最終導致死鎖;可能是程序中自己導致,編寫共享緩存以及自定義的一部分脫離於容器的線程池管理這裏就需要注意了;還有就是有可能是分布式的一些共享文件或者分布式數據庫的鎖導致。
網絡梗阻,網絡不怕沒有,也不怕太快,就怕時快時慢,現在的話叫太不給力了,傷不起啊!而國內現在往往還就是這樣不給力;當去網絡通信調用內容的時候(包括數據庫交互一般也是通過網絡的),就很容易產生焊住的現象,也就是假死,此時很難判定線程到底是怎麼了,除非有提前的監控預案。
其他情況下線程還會死掉嗎?就我個人的經驗來說還沒遇到過,但並非絕不可能,我想在常規的同一個JVM內部操作的線程會死掉的概率隻有係統掛掉,不然SUN的java虛擬機也太不讓人信任了;至少從這一點上我們可以決定在絕大部分情況下線程阻塞的主要原因是上述兩個主要來源。
在明白絕大部分原因的基礎上,這裏已經提出了問題並初步分析了問題,那麼繼續來如何解決這些問題,或者說將問題的概率降低到非常低的程度(因為沒有百分百的高可用性環境,我們隻是要盡量去做到它盡量完美,亞馬遜的雲計算也有宕機的驚人時刻,嗬嗬)。
3.1. 多線程焊住或者死掉如何捕獲和處理?
說到捕獲,學習java朋友肯定第一想到的是try catch,但是線程假死根本不會拋異常,如何知道線程死掉了呢?
這需要從我們的設計層麵下手,對於後來java提供的線程池也可以比較放心的使用,但是對於很多非常複雜的線程管理,需要我們自己來設計管理。如何捕獲我們用一個生活中的例子來舉例,下一長中將它反饋到實際的係統設計上。
首先多線程自己死掉了它肯定不知道,就想一個人自己喝醉了或者被被人打暈了一樣,嗬嗬,那麼如何才能知道它的現狀了?提出兩種現實思路,一個是有一個跟班的人,而另一種是它上麵有一個領導帶一群人出來玩,下麵人丟了一個它肯定要去找。
先看看第一種思路,跟班那個我假如他平時什麼也不做,就跟在前者後麵,當發現前者倒下,自己馬上跟上去頂替工作,這也是係統架構上經常采用的冗餘主從切換,可能一主多從;而雲計算也是在基礎上的進一步做的異地分流切換和資源動態調度(也就是事情少了,這些人可以去做其他的事情或者睡覺養精神並且為國家節約糧食,當這邊的事情忙不過來,會有做其它事情的人或者待命的人來幫著做這些事情;甚至於此地遭到地震洪水類天災什麼的,異地還有機構可以頂替同樣的工作內容,這樣讓對外的服務永遠不斷間斷下來,也就是傳說中的24*7的高可用性服務),但是這樣冗餘太大,成本將會非常巨大。
再看看第二種服務,上麵有一個老大,它過一小會看看這幫小弟在做什麼,是不是遇到了困難,那裏忙它在上麵動態調配這資源;好像這種模式很好呢?小弟要是多了,它就忙不過來了,因為資源的分配是需要提前明白下麵資源的細節的,不然這個領導不是好領導;那麼再細想下去,我們可以用多個老大,每個老大帶領一個小團隊,團隊之間可以資源調配,但是團隊內部可以由老大自己掌控一切,老大的上麵還有個老總它隻關心於老大再做什麼,而不需要關心小弟們的行為,這樣大家的事情就平均起來了;那麼問題了又出來了,小弟的問題是可以透明的看到了,要是那個老大出事了甚至於老總出事了怎麼辦?此時結合第一種思想,我們此時就隻需要再老總下麵掛一個跟班的,集合兩種模式的特征,也就是小弟不需要配跟班的,這樣就節約了很大的成本(因為葉子節點的數量是最多的),而上麵的節點我們需要有跟班的,如果想最大程度節約成本,隻需要讓主節點配置一個或者多個跟班就可以,但是這樣恢複成本就上去了,因為恢複信息需要逐層找到內容才行,一般我們沒有必要在這個基礎上再進一步去節約成本。
這些是現實的東西,如何結合到計算機係統架構中,再回到本文的多線程設計上,第四章中一起來探討一下。
4、如何設計一個具有可擴展性的多線程處理器。
其實在第三章中,已經從生活的管理模式上找到了很多的解決方案,這也是我個人在解決問題上慣用的手段,因為個人認為再複雜的數學算法也沒有人性本身的複雜,生活中的種種手段若用於計算機中可能會得到很多神奇的效果。
如果自己不使用任何開源技術,要做一個多線程處理的框架應該從何下手,在上麵分析的基礎上,我們一般會將一個專門處理多線程的係統至少分解為主次二層,也就是主線程引導多個運行線程去處理問題;好了,此時我們需要解決以下幾個問題:
a)多個線程處理的內容是類似的,如何控製並發征用數據或者說降低並發熱點的粒度。
方法1:hash散列思想將會是優秀的原則,按照數據特征進行分解數據框,每個框的數據規則按照一種hash規則分布,hash散列對於編程容易遍曆,而且計算速度非常迅速,幾乎可以忽略掉定位分組的時間,但結構擴展過程比較麻煩,但在多線程設計中一般不需要考慮這個問題。
方法2:range分布,range範 圍分布數據是提前讓管理者知道數據的大致分布情況,並按照一種較為平均的規則交給下麵的運作線程去去處理自己範圍內的數據,相互之間的數據也是沒有任何交叉的,其擴展性較好,可以任意擴展,如果分解的數量不受控製的話,分解過多,會造成定位範圍比較慢一點,但是多線程設計中也一般不用考慮這個問題,因為程序是由自己編寫的。
方法3:位圖分布,即數據具有位圖規則,一般是狀態,這種數據按照位圖分布後,線程可以設立為位圖個數,找到自己的位圖段數據即可做操作,而不需要做進一步的更新,但是往往位圖數量有限,而需要處理的數據量很大,一個線程處理一個位圖下的所有數據也往往力不從心,若多個線程處理一個位圖又會重蹈覆轍。
三種方法各自有優缺點,所以我們往往采用組合模式來講真個係統的架構達到比較完美的狀態,當然沒有完美的東西,隻有最適應於當前應用環境的架構,所以設計前需要考慮很多預見性問題;關於這種數據分布更多的用於架構,但是架構的基礎也來源於程序設計思想,兩者思想都是一致的,有關架構和數據存儲分布,後麵有機會單獨討論。
b)線程死掉如何發現(以及處理):
管理線程除有運行動作的線程外,還有1~N跟班,個數根據實際情況決定,至少要有一個當管理線程掛掉可以馬上頂替工作,另外還有應當有一個線兩程去定期檢測線程的運行情況,由於它隻負責這件事情,所以很簡單,而且這一組中的線程誰死掉都可以相互替換工作並重啟新的線程去替代,這個檢測的周期不用太快、也不用太慢,隻要應用可以接受就可以,因為掛掉些東西,應用阻塞一點時間是非常正常的事情。
發現線程有阻塞現象,在執行中找到了某種以外而阻塞,導致的原因我們上麵已經分析過,解決的方法一般是在探測幾次(這個次數一般是基於配置的)後發現都是處於阻塞狀態,就基本可以認為它是錯誤的了;錯誤的情況此時需要給該線程執行一個interrupt()方法,此時線程內部的執行會自動的拋出一個異常,也就是理解執行線程的內容的時候尤其是帶有網絡操作的時候需要帶上一個try catch,執行部分都在try中,當出現假死等現狀的時候,外部探測到使用一個interrupt()方法,運行程序就會跳轉到catch之中,這個裏麵就不存在征用資源的問題,而快速的將自己的需要回滾的內容執行完,並認為線程執行結束,相應的資源也會得到釋放,而使用stop方法之所以現在不推薦是因為它不會釋放資源,會導致很多的問題。
另外寫代碼之前如果涉及到一些網絡操作,一定要對你所使用的網絡交互程序有很多的深入認識,如socket交互時,一般情況下如果對方由於網絡原因(一般是有IP當時端口不對或者網段的協議不通)導致在啟動連接對方時,socket連接對方好幾分鍾後才會顯示是超時連接,這是默認的,所以你需要提前設置一個啟動連接超時保證網絡是可以通信的,再進行執行(注意socket裏麵還有一個超時是連接後不斷的時間,前者為連接之前設置的一個啟動連接超時時間,一般這個時間很短,一般是2秒就很長了,因為2秒都連接不上這個網絡就基本連接不上了,而後者是運行,有些交互可能長達幾小時也有可能,但類似這種交互建議采用異步交互,以保證穩定運行)。
C)如果啟動和管理二級管理線程組:
上麵有一個主線程來控製啟動和關閉,這裏可以將這些線程在start前的setDaemon(true),那麼該線程將會被設立為後台線程,所謂後台線程就是當主線程執行完畢釋放資源後,被主線程創建的這些線程將會自動釋放資源並死掉,如果一個線程被設置為後台線程,若在其run方法內部創建的其他子線程,將會自動被創建為後台線程(如果在構造方法中創建則不是這樣)。
管理線程也可以像二級線程一樣來管理子節點,隻要你的程序不怕寫得夠複雜,雖然需要使用非常好的代碼來編寫,並且需要通過很複雜的測試才會穩定運行,但是一旦成功,這個框架將會是非常漂亮和穩定,而且也是高可用的。
5、多線程在多主機下的擴展-集群
其實我們在上麵以及提及了一些分布式的知識,也可以叫做數據的分區知識(在網絡環境利用PC實現類似於同一個主機上的分區模式,基本就可以稱為數據是分布式存儲的)。
但是這裏提到的集群和這個有一些區別,可以說分布式中包含了集群的概念,但是一般集群的概念也有很多的區別,並且要分app集群和數據庫集群。
集群一般是指同一個機組下多個節點(同一台機器也可以部署多個節點),這些節點幾乎去完成同樣的事情,或者說類似的事情,這就和多線程扯在一起了,多線程也正是如此,對比來看就是多線程調度在多主機群組下的實現,所以參照app集群來說,一般有一個管理節點,它幾乎幹很少的事情,因為我們不想讓它掛掉,因為他雖然幹的事情少,但是卻非常重要,一個是從它那裏可以得到每一個節點的一些應用部署和配置,以及狀態等等信息;另外是代理節點或者叫做分發節點,它幾乎在管理節點的控製之下隻做分發的,當然要保證session一致性。
集群在多線程中的另一個體現就是掛掉一台,其餘的可以頂替,而不會導致全盤死掉;而集群組相當於一個大的線程組,相關牽製管理,也相互可以失敗切換,而多個業務會或者多種工具項會劃分為不同的集群組,這就類似於我們設計線程中的三層線程模式的中多組線程組的模式,每組線程組內部都有自己個性化的屬性和共享屬性。
而麵對數據庫集群,就相對比app集群要複雜,app在垂直擴展時幾乎隻會受到分發節點能力的限製,而這部分是可以調整的,所以它在垂直擴展的過程中非常方便,而數據庫集群則不一樣,它必須保證事務一致性,並實現事務級別切換和一定程度上的網格計算能力,中間比較複雜的也在內存這塊,因為它的數據讀入到內存中要將多個主機的內存配置得像一個內存一樣(通過心跳完成),而且需要得到動態擴展的能力,這也是數據庫集群下擴展性收到限製發展的一個原因之一。
App難道沒有和數據庫一樣的困難嗎?有,但是粒度相對較小,app集群一般不需要考慮事務,因為一個用戶的session一般在不出現宕機的情況下,是不會出現複製要求的,而是一直會訪問指定的一台機器,所以它們之間幾乎不需要通信;而耦合的粒度在於應用本身的設計,有部分應用係統會自己寫代碼將一些內容初始化注入到內存中,或者注入到app本地的一個文件中作為文件緩存;這樣當這些數據發生改變時他們先改數據庫,再修改內存或者通知內存失效;數據庫由於集群使用心跳連接,所以保持一致性,而app這邊的數據由於隻修改掉了自身的內存相關信息,沒有修改掉其他機器的內存信息,所以必然導致訪問其他數據的機器上的內容是不一致的;至於這部分的解決方案,根據實際項目而定,有通過通信完成的,也有通過共享緩衝區完成(但這種方式又回到共享池資源征用產生的鎖了),也有通過其他方式完成。
大型係統架構最終數據分布,集中式管理,分布式存儲計算,業務級別橫向切割,同業務下app垂直分隔,數據級別散列+range+位圖分布結構,異地分流容災,待命機組和資源調配的整合,這一切的基礎都來源於多線程的設計思想架構在分布式機組上的實現。
6、WEB應用的多線程以及長連接原理
WEB應用中會對一些特殊的業務服務做特殊的服務器定製,類似一些高並發訪問係統甚至於專門用於瞬間高並發的係統(很多時候係統不怕高並發,而是怕瞬間高並發)但他們的訪問往往比較簡單,主要用於事務的處理以及數據的一致性保障,他們在數據的處理上要求在數據庫端也不允許有太大的計算量,計算一般在app中去完成,數據庫一般隻是做存、取、事務一致性動作,這類一般屬於特殊的OLTP係統;還有大分類一類是屬於並發量不算太大,但每次處理的數據和計算往往比較多,一把說的是OLAP類的係統,而數據的來源一般是OLTP,OLAP每次處理的數據量可能會非常大,一般在類型收集和統計上進行數據dump,需要將OLTP中的數據按照某種業務規則方麵查詢和檢索的方法提取出來組織為有效信息存儲在另一個地方,這個地方有可能還是數據庫,但也有可能不是(數據庫的計算能力雖然是數據上最強的但是它在實際應用中它是最慢的一種東西,因為數據庫更多的是需要保證很多事務一致性和鎖機製問題,以及一些中間解析和優化等等產生的開銷是非常大的,而且應用程序與之交互過程是需要通過網絡完成,所以很多數據在實際的應用中並不一定非要用數據庫);這兩類係統在設計和架構上都有很大的區別,但普通係統兩者都有特征,但是都不是那麼極端,所以不用考慮太多,這裏需要提到的是一類非常特殊的係統,是實時性推送數據並高並發的係統,到目前為止我個人不知道將它歸並到哪一類係統中,這的確很特殊的一類係統。
這類係統如:高並發訪問中,而且需要將同一個平台下的數據讓客戶端較為實時的得到內容,這類網站不太可能一次獲取非常多的內容到客戶端再訪問,而肯定是通過很多異步交互過程來完成的,下麵簡單說下這個異步交互。
Web異步交互的所有框架基礎都是ajax,其餘的類似框架都是在這個基礎上完成的;那麼此時ajax應該如何來控製交互才能得到幾乎接近於實時的內容呢?難道通過客戶端不斷去刷新相同的URL?那要是客戶端非常多,類似於一個大型網站,可能服務器端很快會宕機,除非用比正常情況高出很多倍的服務器成本去做,而且更多的服務器可能在架構上也需要改造才能發揮出他們的性能(因為在服務器的架構上,1 + 1永遠是小於2的性能,更多的服務器在開銷)。
想到的另一種辦法就是從服務器端向客戶端推送數據,那麼問題是如何推送,這類操作是基於一種長連接機製完成,長連接即不斷開的連接,客戶端采用ajax與後端通信時,後端的反饋信息隻要未曾斷開就可視為一種長連接的機製;很多是通過socket與服務器端通信,也可以使用ajax,不過ajax需要在其上麵做很多的處理才行。
服務器端也是必須使用對應的策略,現在較多的是javaNIO,相對BIO性能要低一點,但是也是很不錯的,它在獲取到用戶請求時並不是馬上為用戶請求分配線程去處理,而是將請求進行排隊,而排隊的過程可以自己去控製粒度,而線程也將作為線程池的隊列進行分配處理,也就是服務器端對客戶端的請求是異步響應(注意這裏不是ajax單純的異步交互,而是服務器端對請求的異步響應),它對很多請求的響應並非及時,當發生數據變化時,服務器第一時間通過請求列表獲取到客戶端session列表並與之輸出內容,類似於服務器端主動推送數據向客戶端;而異步交互的好處是服務器端並不會為每一個客戶端分配或新申請一個線程,這樣會導致高並發時引起的資源分配不過來導致的內存溢出現象;解決了上述兩個問題後,另外還有一個問題需要解決的是,當一個線程在處理一個請求任務時,由於線程處理一個任務完成前除非死掉或者焊住,否則是不會斷開下來的,這個是肯定的(我們可以將一些大任務切割為一些小任務,線程就處理的速度就會快很多了),但是有一個問題是,服務器端的這個線程可能很快處理好了需要處理的數據內容並向客戶端推送,但是客戶端由於各類網絡通信問題,導致遲遲不能接受完成,此時該線程也會被占用些不必要的時間,那麼是否在這個中間需要進一步做一層斷點傳送的緩存呢?緩存不僅僅是屬於在斷點數據需要時取代應用服務器的內容,異步斷點向客戶端輸出信息,同時將應用服務器處理的時間幾乎全部集中在數據和業務處理,而不是輸出網絡上的很多占用,有關網絡緩存有很多種做法,後續有機會和大家一起探討關於網絡緩存的知識吧。
最後更新:2017-04-02 06:51:39
上一篇:
Android手機無法使用debug解決方法
下一篇:
停止啟用了安全性的WAS Server而不手動輸入密碼之第二種選擇
[C#][MySql]統計數據表總行數函數--C#和MySQL開發
科技圈大佬童年照,你認識幾張?
清除xp,win7快捷方式小箭頭
Javascript基礎學習之基本語法
Android Dialog用法
WCF中的Binding模型之一: Binding模型簡介
移動硬盤裏麵的文件打不開怎麼辦怎麼免費恢複
Android開發13——內容提供者ContentProvider的基本使用
Android開發7——android.database.CursorIndexOutOfBoundsException:Index -1 requested, with a size of 1
Android 關於嵌套listView時onItemClick事件不響應的解決辦法