<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 262,  comments - 221,  trackbacks - 0

    多線程編程一直是程序員比較頭痛和心虛的地方,因為線程執(zhí)行順序的不可預(yù)知性和調(diào)試時候的困難,讓不少人在面對多線程的情況下選擇了逃避,采用單線程的方式,其實只要我們對線程有了明確的認識,再加上Java內(nèi)置的對多線程的天然支持,多線程編程不再是一道難以逾越的鴻溝。

    目錄:


    【一】進程、線程、并發(fā)執(zhí)行
    【二】JVM與多線程
    【三】Java語言對多線程的支持
    【四】線程的狀態(tài)切換
    【五】Java中線程的調(diào)度API
    【六】參考文章



     【一】進程、線程、并發(fā)執(zhí)行

    關(guān)于進程、線程、并發(fā)執(zhí)行的概念,我們先來看下面的一段話:

    “一般來說,當運行一個應(yīng)用程序的時候,就啟動了一個進程,當然有些會啟動多個進程。啟動進程的時候,操作系統(tǒng)會為進程分配資源,其中最主要的資源是內(nèi)存空間,因為程序是在內(nèi)存中運行的。

    在進程中,有些程序流程塊是可以亂序執(zhí)行的,并且這個代碼塊可以同時被多次執(zhí)行。實際上,這樣的代碼塊就是線程體。線程是進程中亂序執(zhí)行的代碼流程。當多個線程同時運行的時候,這樣的執(zhí)行模式成為并發(fā)執(zhí)行。”

    上面這段話引自51CTO網(wǎng)站“熔巖”的博客一篇文章《Java多線程編程總結(jié)》,讀者可參考本文獲得更詳細的知識。

    下面我以一個日常生活中簡單的例子來說明進程和線程之間的區(qū)別和聯(lián)系:

    這副圖是一個雙向多車道的道路圖,假如我們把整條道路看成是一個“進程”的話,那么圖中由白色虛線分隔開來的各個車道就是進程中的各個“線程”了。

    ①這些線程(車道)共享了進程(道路)的公共資源(土地資源)。

    ②這些線程(車道)必須依賴于進程(道路),也就是說,線程不能脫離于進程而存在(就像離開了道路,車道也就沒有意義了)。

    ③這些線程(車道)之間可以并發(fā)執(zhí)行(各個車道你走你的,我走我的),也可以互相同步(某些車道在交通燈亮時禁止繼續(xù)前行或轉(zhuǎn)彎,必須等待其它車道的車輛通行完畢)。

    ④這些線程(車道)之間依靠代碼邏輯(交通燈)來控制運行,一旦代碼邏輯控制有誤(死鎖,多個線程同時競爭唯一資源),那么線程將陷入混亂,無序之中。

    ⑤這些線程(車道)之間誰先運行是未知的,只有在線程剛好被分配到CPU時間片(交通燈變化)的那一刻才能知道


    【二】JVM與多線程
    Java編寫的程序都運行在在Java虛擬機(JVM)中,在JVM的內(nèi)部,程序的多任務(wù)是通過線程來實現(xiàn)的。

    每用java命令啟動一個java應(yīng)用程序,就會啟動一個JVM進程。在同一個JVM進程中,有且只有一個進程,就是它自己。在這個JVM環(huán)境中,所有程序代碼的運行都是以線程來運行的。JVM找到程序程序的入口點main(),然后運行main()方法,這樣就產(chǎn)生了一個線程,這個線程稱之為主線程。當main方法結(jié)束后,主線程運行完成。JVM進程也隨即退出。

    操作系統(tǒng)將進程線程進行管理,輪流(沒有固定的順序)分配每個進程很短的一段時間(不一定是均分),然后在每個進程內(nèi)部,程序代碼自己處理該進程內(nèi)部線程的時間分配,多個線程之間相互的切換去執(zhí)行,這個切換時間也是非常短的


    【三】Java語言對多線程的支持
    Java語言對多線程的支持通過類Thread和接口Runnable來實現(xiàn)。這里就不多說了,讀者可以參考《Java多線程編程總結(jié)》這篇文章得到更多的信息。這里重點強調(diào)兩個地方:

    // 主線程其它代碼段
    ThreadClass subThread = new ThreadClass();
    subThread.start();
    // 主線程其它代碼段
    subThread.sleep(1000);

    有人認為以下的代碼在調(diào)用start()方法后,肯定是先啟動子線程,然后主線程繼續(xù)執(zhí)行。在調(diào)用sleep()方法后CPU什么都不做,就在那里等待休眠的時間結(jié)束。實際上這種理解是錯誤的。因為:

    start()方法的調(diào)用后并不是立即執(zhí)行多線程代碼,而是使得該線程變?yōu)榭蛇\行態(tài)(Runnable),什么時候運行是由操作系統(tǒng)決定的。

    Thread.sleep()方法調(diào)用目的是不讓當前線程獨自霸占該進程所獲取的CPU資源,以留出一定時間給其他線程執(zhí)行的機會(也就是靠內(nèi)部自己協(xié)調(diào))。


    【四】線程的狀態(tài)切換
    前面我們提到,由于線程何時執(zhí)行是未知的,只有在CPU為線程分配到時間片時,線程才能真正執(zhí)行。在線程執(zhí)行的過程中,由可能會因為各種各樣的原因的原因而暫停(就像前面所舉的例子一樣:汽車只有在交通燈變綠的時候才能夠通行,而且在行駛的過程中可能會出現(xiàn)塞車,等待其它車輛通行或轉(zhuǎn)彎的狀況)。

    這樣線程就有了“狀態(tài)”的概念,下面這副圖,是從《Java多線程編程總結(jié)》一文中摘錄出來的。很好的反映了線程在不同情況下的狀態(tài)變化


    1、新建狀態(tài)(New):
         新創(chuàng)建了一個線程對象。

    2、就緒狀態(tài)(Runnable):
         線程對象創(chuàng)建后,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運行線程池中,變得可運行,等待獲取CPU的使用權(quán)。

    3、運行狀態(tài)(Running):
         就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。

    4、阻塞狀態(tài)(Blocked):
         阻塞狀態(tài)是線程因為某種原因放棄CPU使用權(quán),暫時停止運行。直到線程進入就緒狀態(tài),才有機會轉(zhuǎn)到運行狀態(tài)。阻塞的情況分三種:

    ①等待阻塞:運行的線程執(zhí)行wait()方法,JVM會把該線程放入等待池中。
    ②同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM把該線程放入鎖池
    ③其他阻塞:運行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時,JVM會把該線程置為阻塞狀態(tài)。當sleep()狀態(tài)超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)。

    5、死亡狀態(tài)(Dead):
         線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。


    【五】Java中線程的調(diào)度API


    Java中關(guān)于線程調(diào)度的API最主要的有下面幾個:

    ①線程睡眠:Thread.sleep(long millis)方法

    ②線程等待:Object類中的wait()方法

    ③線程讓步:Thread.yield() 方法

    ④線程加入:join()方法

    ⑤線程喚醒:Object類中的notify()方法

    關(guān)于這幾個方法的詳細應(yīng)用,可以參考SUN的API,及《Java多線程編程總結(jié)》一文第七部分“線程的調(diào)度”。這里我重點總結(jié)一下這幾個方法的區(qū)別和使用:

    備注:sleep方法與wait方法的區(qū)別:
    ①sleep方法是靜態(tài)方法,wait方法是非靜態(tài)方法。
    ②sleep方法在時間到后會自己“醒來”,但wait不能,必須由其它線程通過notify(All)方法讓它“醒來”
    ③sleep方法通常用在不需要等待資源情況下的阻塞,像等待線程、數(shù)據(jù)庫連接的情況一般用wait

    備注:sleep/wait與yeld方法的區(qū)別:
    ①調(diào)用sleep或wait方法后,線程即進入block狀態(tài),而調(diào)用yeld方法后,線程進入runnable狀態(tài)

    備注:wait與join方法的區(qū)別:
    ①wait方法體現(xiàn)了線程之間的互斥關(guān)系,而join方法體現(xiàn)了線程之間的同步關(guān)系
    ②wait方法必須由其它線程來解鎖,而join方法不需要,只要被等待線程執(zhí)行完畢,當前線程自動變?yōu)榫途w
    ③join方法的一個用途就是讓子線程在完成業(yè)務(wù)邏輯執(zhí)行之前,主線程一直等待直到所有子線程執(zhí)行完畢。


    【六】參考文章

    www.51cto.com網(wǎng)站 熔巖的博文《Java多線程編程總結(jié)》


    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2008-09-02 10:50 Paul Lin 閱讀(3908) 評論(3)  編輯  收藏 所屬分類: J2SE


    FeedBack:
    # re: 多線程編程的基礎(chǔ)知識點
    2008-09-02 16:00 | 峰旭
    不錯啊,重新溫習了一遍  回復  更多評論
      
    # re: 多線程編程的基礎(chǔ)知識點
    2008-09-02 16:08 | 尋道者
    版面真好看,內(nèi)容還沒細看,先記號。  回復  更多評論
      
    # re: 多線程編程的基礎(chǔ)知識點
    2008-09-03 09:44 | yz
    版面真好看,內(nèi)容也好!詳細嚴謹!  回復  更多評論
      
    <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 午夜视频在线免费观看| 一道本不卡免费视频| 91视频免费观看高清观看完整| 免费看大美女大黄大色| 自拍偷区亚洲国内自拍| 毛片免费在线观看网址| 亚洲乱码中文字幕在线| 午夜高清免费在线观看| 美女啪啪网站又黄又免费| 亚洲精品国产V片在线观看| 一级毛片无遮挡免费全部| 亚洲偷自拍拍综合网| 成人免费区一区二区三区| 亚洲av鲁丝一区二区三区| 99久久99久久免费精品小说| 亚洲男人的天堂在线| 女人张开腿等男人桶免费视频| 国产人成亚洲第一网站在线播放| 午夜爱爱免费视频| 精品久久久久亚洲| 亚洲色自偷自拍另类小说| 无码人妻一区二区三区免费n鬼沢 无码人妻一区二区三区免费看 | 国产最新凸凹视频免费| 极品美女一级毛片免费| 亚洲人成精品久久久久| 日韩精品久久久久久免费| 狠狠色香婷婷久久亚洲精品| 日本免费网站观看| 中文字幕免费人成乱码中国| 精品亚洲成a人片在线观看| 四虎成人免费网址在线| 黄视频在线观看免费| 久久久亚洲裙底偷窥综合| 国产精品麻豆免费版| 中文字幕在线免费观看视频| 亚洲国产精品综合久久网各| 国产在线不卡免费播放| 最近免费中文字幕MV在线视频3 | 成年人网站免费视频| 日韩在线视频免费| 亚洲欧洲高清有无|