JavaSky
          JavaBird
          posts - 8,  comments - 9,  trackbacks - 0
          什么是多線程:
          多線程是為了使得多個線程并行的工作以完成多項任務,以提高系統(tǒng)的效率。線程是在同一時間需要完成多項任務的時候被實現(xiàn)的。
          使用線程的好處有以下幾點:
          ·使用線程可以把占據(jù)長時間的程序中的任務放到后臺去處理
          ·用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發(fā)某些事件的處理,可以彈出一個進度條來顯示處理的進度
          ·程序的運行速度可能加快
          ·在一些等待的任務實現(xiàn)上如用戶輸入、文件讀寫和網(wǎng)絡收發(fā)數(shù)據(jù)等,線程就比較游泳了。在這種情況下我們可以釋放一些珍貴的資源如內(nèi)存占用等等。
          ====
          什么是多進程:
          進程是程序在計算機上的一次執(zhí)行活動。當你運行一個程序,你就啟動了一個進程。顯然,程序是死的(靜態(tài)的),進程是活的(動態(tài)的)。進程可以分為系統(tǒng)進程和
          用戶進程。凡是用于完成操作系統(tǒng)的各種功能的進程就是系統(tǒng)進程,它們就是處于運行狀態(tài)下的操作系統(tǒng)本身;用戶進程就不必我多講了吧,所有由你啟動的進程都
          是用戶進程。進程是操作系統(tǒng)進行資源分配的單位。
          在Windows下,進程又被細化為線程,也就是一個進程下有多個能獨立運行的更小的單位。
          在同一個時間里,同一個計算機系統(tǒng)中如果允許兩個或兩個以上的進程處于運行狀態(tài),這便是多任務。現(xiàn)代的操作系統(tǒng)幾乎都是多任務操作系統(tǒng),能夠同時管理多個進
          程的運行。
          多任務帶來的好處是明顯的,比如你可以邊聽mp3邊上網(wǎng),與此同時甚至可以將下載的文檔打印出來,而這些任務之間絲毫不會相互干擾。那么這里就涉及到并行
          的問題,俗話說,一心不能二用,這對計算機也一樣,原則上一個CPU只能分配給一個進程,以便運行這個進程。我們通常使用的計算機中只有一個CPU,也就
          是說只有一顆心,要讓它一心多用,同時運行多個進程,就必須使用并發(fā)技術。實現(xiàn)并發(fā)技術相當復雜,最容易理解的是“時間片輪轉(zhuǎn)進程調(diào)度算法”,它的思想簡
          單介紹如下:在操作系統(tǒng)的管理下,所有正在運行的進程輪流使用CPU,每個進程允許占用CPU的時間非常短(比如10毫秒),這樣用戶根本感覺不出來
          CPU是在輪流為多個進程服務,就好象所有的進程都在不間斷地運行一樣。但實際上在任何一個時間內(nèi)有且僅有一個進程占有CPU。
          如果一臺計算機有多個CPU,情況就不同了,如果進程數(shù)小于CPU數(shù),則不同的進程可以分配給不同的CPU來運行,這樣,多個進程就是真正同時運行的,這便是并行。但如果進程數(shù)大于CPU數(shù),則仍然需要使用并發(fā)技術。
          在Windows中,進行CPU分配是以線程為單位的,一個進程可能由多個線程組成,這時情況更加復雜,但簡單地說,有如下關系:
          總線程數(shù)<= CPU數(shù)量:并行運行
          總線程數(shù)> CPU數(shù)量:并發(fā)運行
          并行運行的效率顯然高于并發(fā)運行,所以在多CPU的計算機中,多任務的效率比較高。但是,如果在多CPU計算機中只運行一個進程(線程),就不能發(fā)揮多CPU的優(yōu)勢。
          這里涉及到多任務操作系統(tǒng)的問題,多任務操作系統(tǒng)(如Windows)的基本原理是:操作系統(tǒng)將CPU的時間片分配給多個線程,每個線程在操作系統(tǒng)指定的時
          間片內(nèi)完成(注意,這里的多個線程是分屬于不同進程的).操作系統(tǒng)不斷的從一個線程的執(zhí)行切換到另一個線程的執(zhí)行,如此往復,宏觀上看來,就好像是多個線
          程在一起執(zhí)行.由于這多個線程分屬于不同的進程,因此在我們看來,就好像是多個進程在同時執(zhí)行,這樣就實現(xiàn)了多任務.
          架構(gòu)設計:多進程還是多線程
          就像莎士比亞的“To be, or not to be, that is the
          question”始終困擾著哈姆雷特,對于“進程還是線程?”這個問題,也經(jīng)常困擾著那些進行軟件架構(gòu)設計的家伙。所以今天打算聊一下我對這個問題的體
          會。假如你還搞不清楚線程和進程的區(qū)別,請先找本操作系統(tǒng)原理的書好好拜讀一下,再回來看帖。
            由于這個問題很容易引發(fā)口水戰(zhàn),事先聲明如下:多進程和多線程,無法一概而論地說誰比誰好。因此本帖主要描述特定場景(與我所負責的產(chǎn)品相關)下,進程和線程的權(quán)衡經(jīng)驗,僅供大伙兒參考。

            由于特定場景是本帖討論的前提,先說說我目前負責的產(chǎn)品的特點:業(yè)務邏輯比較復雜、業(yè)務數(shù)據(jù)量比較大、對數(shù)據(jù)實時處理的性能要求比較高、對健壯性和安全性要求比較高、要求跨平臺(包括操作系統(tǒng)、數(shù)據(jù)庫)、某些情況下需要分布部署。

            上面說了一大堆,其實有不少的應用系統(tǒng)符合上述特點,比如:某些網(wǎng)絡游戲服務器、某些金融行業(yè)的業(yè)務系統(tǒng)、某些電子商務的交易系統(tǒng)等等。如果你正在從事的是類似的應用系統(tǒng)的設計,希望我下面介紹的經(jīng)驗對你有幫助。

             進程顆粒度問題

            大伙兒應該明白,進程和線程都是處理并發(fā)(concurrency)的手段。對于上述這種比較復雜的系統(tǒng),如果你企圖全部用進程(見注1)或者
          全部用線程(見注2)來處理并發(fā),估計會死得很難看。所以,關鍵問題就是如何在進程和線程之間進行平衡(也就是確定進程顆粒度的問題)。

            我個人建議,盡量以業(yè)務邏輯的單元來劃分進程。這樣做的好處有如下幾點:

            1、避免扯皮

            一般來說,某個固定業(yè)務邏輯的開發(fā)人員也是相對固定的。如果業(yè)務邏輯對應的某個進程崩潰了,測試人員容易快速定位肇事者,然后直接提交Bug給他/她。

            反之,一個進程搞得太龐大,N多人摻和在里面,一旦進程崩潰了,相關編程人員之間很容易互相扯皮,不利于維護安定團結(jié)的局面;另外,由于測試人員經(jīng)常搞不清楚Bug屬于誰,經(jīng)常給錯Bug,也容易制造人民內(nèi)部矛盾。

            從上面可以看出來,相對細的進程顆粒度能夠避免一些管理上的麻煩。由于XXX經(jīng)常教導我們:“穩(wěn)定壓倒一切”,所以該優(yōu)點列第一條。

            2、健壯性、容錯性

            一般來說,開發(fā)人員的水平參差不齊,優(yōu)秀的畢竟是少數(shù)(具體參見“二八原理系列”的帖子)。所以難免會有菜鳥程序員搞出低級錯誤,而有些低級錯誤是致命的,會導致進程的崩潰。

            如果你是以業(yè)務邏輯劃分進程,一個業(yè)務邏輯的進程崩潰,對其它業(yè)務邏輯的影響不大(除非是該業(yè)務邏輯的依賴方);因此就不會出現(xiàn)“注2”提到的問題。

            3、分布式

            我常碰見的分布式部署需求,一般都是按照業(yè)務邏輯的維度來劃分。比如系統(tǒng)中有一個認證模塊,里面包含有敏感的用戶認證信息。這時候客戶就會要求把該模塊單獨部署在一臺經(jīng)過安全加固的主機中(以防階級敵人搞破壞)。

            如果是以業(yè)務邏輯為單位劃分進程,要滿足上述的部署需求就相對容易了(只要再配合恰當?shù)倪M程間通訊機制,下面會提到)。

            另外,支持分布式部署還可以順帶解決性能問題。比如某個業(yè)務邏輯模塊特別消耗硬件資源(比如內(nèi)存、CPU、硬盤、帶寬),就可以把它拿出去單獨放一臺機器上跑。

            4、跨編程語言

            這個好處可能很多人容易忽略。一般來說,每個編程語言都有各自的優(yōu)缺點。如果你通過業(yè)務邏輯劃分進程,就可以根據(jù)不同的業(yè)務邏輯的特點來選擇合適的編程語言。

            比如:對于性能敏感的模塊,我就使用C++搞定;而對于一些業(yè)務邏輯密集型的模塊,則使用Java或Python開發(fā)。

             進程間通訊(以下簡稱IPC)問題

            既然不可能把整個系統(tǒng)放入一個進程,那就必然會碰到IPC的問題。下面就來說一下該如何選擇IPC。

            各種操作系統(tǒng)里面,有很多稀奇古怪的IPC類型。由于要考慮跨平臺,首先砍掉一批(關于IPC的跨平臺問題,我在“跨平臺開發(fā)”系列中會提
          到)。剩下的IPC類型中,能夠進行數(shù)據(jù)傳輸?shù)腎PC就不多了,主要有如下幾種:套接字(以下簡稱Socket)、共享內(nèi)存、管道、文件。

            其中Socket是我強烈推薦的IPC方式,理由如下:使用Socket可以天然地支持分布式部署;使用Socket可以比較容易地實現(xiàn)多種編
          程語言的混合(比如C++、Java、Python、Flex都支持Socket);使用Socket還可以省掉了一大坨“鎖操作”的代碼。

            列位看官中,或許有人在擔心Socket的性能問題,其實大可不必多慮。當兩個進程在本機上進行Socket通訊時,由于可以使用
          localhost環(huán)回地址,數(shù)據(jù)不用經(jīng)過物理網(wǎng)卡,操作系統(tǒng)內(nèi)核還可以進行某些優(yōu)化。這種情況下,Socket相對其它幾種IPC機制,不會有太大的性
          能偏差。

            最后再補充一下,Socket方式也可以有效防止扯皮問題。舉個例子:張三寫了一個進程A,李四寫了一個進程B,進程A通過Socket方式發(fā)
          數(shù)據(jù)給進程B。突然有一天,兩個進程的通訊出故障了。然后張三就說是李四接收數(shù)據(jù)出錯;李四就說張三發(fā)送數(shù)據(jù)出錯。這時候怎么辦捏?很簡單,隨便找個
          Sniffer軟件當場抓一下數(shù)據(jù)包并Dump出來看,問題就水落石出了。

             為啥還要線程?

            上面說了這么多進程的好處,有同學要問了:“那線程有什么用捏?”總的來說,使用線程出于兩方面的考慮:性能因素和編碼方便。

            1、性能因素

            由于某些操作系統(tǒng)(比如Windows)中的進程比較重型,如果頻繁創(chuàng)建進程或者創(chuàng)建大量進程,會導致操作系統(tǒng)的負載過高。舉例如下:

            假設你要開發(fā)一個類似Web Server的應用。你針對每一個客戶端請求創(chuàng)建一個對應的進程用于進行數(shù)據(jù)交互(是不是想起了古老的CGI :-)。一旦這個系統(tǒng)擴容,用戶的并發(fā)連接數(shù)一增加,你的應用立馬死翹翹。

            上面的例子表明,跨平臺軟件系統(tǒng)的進程數(shù)要保持相對穩(wěn)定。如果你的進程數(shù)會隨著某些環(huán)境因素呈線性增長,那就相當不妙了(順帶說一下,如果線程數(shù)會隨著環(huán)境因素呈線性增長,也相當不妙)。而根據(jù)業(yè)務邏輯的單元劃分進程,順便能達到“進程數(shù)的相對穩(wěn)定”的效果。

            2、編碼方面

            由于業(yè)務邏輯內(nèi)部的數(shù)據(jù)耦合比較緊密。如果業(yè)務邏輯內(nèi)部的并發(fā)也用進程來實現(xiàn),可能會導致大量的IPC編碼(任意兩個進程之間只要有數(shù)據(jù)交互,就得寫一坨IPC代碼)。這或許會讓相關的編程人員怨聲載道。
            當然,編碼方面的問題也不是絕對的。假如你的系統(tǒng)有很成熟且方便易用的IPC庫,可以比較透明地封裝IPC相關操作,那這方面的問題也就不存在了。 

          魚還是熊掌:淺談多進程多線程的選擇

          關于多進程和多線程,教科書上最經(jīng)典的一句話是“進程是資源分配的最小單位,線程是CPU調(diào)度的最小單位”,這句話應付考試基本上夠了,但如果在工作中遇到類似的選擇問題,那就沒有這么簡單了,選的不好,會讓你深受其害。
          經(jīng)常在網(wǎng)絡上看到有的XDJM問“多進程好還是多線程好?”、“Linux下用多進程還是多線程?”等等期望一勞永逸的問題,我只能說:沒有最好,只有更好。根據(jù)實際情況來判斷,哪個更加合適就是哪個好。
          我們按照多個不同的維度,來看看多線程和多進程的對比(注:因為是感性的比較,因此都是相對的,不是說一個好得不得了,另外一個差的無法忍受)。

          看起來比較簡單,優(yōu)勢對比上是“線程 3.5 v 2.5 進程”,我們只管選線程就是了?
          呵呵,有這么簡單我就不用在這里浪費口舌了,還是那句話,沒有絕對的好與壞,只有哪個更加合適的問題。我們來看實際應用中究竟如何判斷更加合適。
          1)需要頻繁創(chuàng)建銷毀的優(yōu)先用線程
          原因請看上面的對比。
          這種原則最常見的應用就是Web服務器了,來一個連接建立一個線程,斷了就銷毀線程,要是用進程,創(chuàng)建和銷毀的代價是很難承受的
          2)需要進行大量計算的優(yōu)先使用線程
          所謂大量計算,當然就是要耗費很多CPU,切換頻繁了,這種情況下線程是最合適的。
          這種原則最常見的是圖像處理、算法處理。
          3)強相關的處理用線程,弱相關的處理用進程
          什么叫強相關、弱相關?理論上很難定義,給個簡單的例子就明白了。

          般的Server需要完成如下任務:消息收發(fā)、消息處理。“消息收發(fā)”和“消息處理”就是弱相關的任務,而“消息處理”里面可能又分為“消息解碼”、“業(yè)
          務處理”,這兩個任務相對來說相關性就要強多了。因此“消息收發(fā)”和“消息處理”可以分進程設計,“消息解碼”、“業(yè)務處理”可以分線程設計。
          當然這種劃分方式不是一成不變的,也可以根據(jù)實際情況進行調(diào)整。
          4)可能要擴展到多機分布的用進程,多核分布的用線程
          原因請看上面對比。
          5)都滿足需求的情況下,用你最熟悉、最拿手的方式
          至于“數(shù)據(jù)共享、同步”、“編程、調(diào)試”、“可靠性”這幾個維度的所謂的“復雜、簡單”應該怎么取舍,我只能說:沒有明確的選擇方法。但我可以告訴你一個選擇原則:如果多進程和多線程都能夠滿足要求,那么選擇你最熟悉、最拿手的那個。
          需要提醒的是:雖然我給了這么多的選擇原則,但實際應用中基本上都是“進程+線程”的結(jié)合方式,千萬不要真的陷入一種非此即彼的誤區(qū)。
          轉(zhuǎn)自:http://blog.csdn.net/jw212/article/details/5928995

          posted on 2012-09-21 18:07 JavaBird 閱讀(504) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 怀来县| 肃宁县| 阜康市| 霍州市| 嘉荫县| 涡阳县| 台东县| 天等县| 蛟河市| 拉萨市| 黎城县| 绩溪县| 清远市| 江孜县| 靖州| 贵溪市| 三门县| 大洼县| 怀远县| 同江市| 铜陵市| 肥乡县| 化隆| 西城区| 康马县| 安福县| 霞浦县| 循化| 赞皇县| 盐源县| 夏津县| 泗洪县| 峨边| 五华县| 鸡泽县| 黑山县| 新津县| 定日县| 思茅市| 夏河县| 扎鲁特旗|