Java, Only Java!

          統(tǒng)計(jì)

          留言簿(20)

          積分與排名

          好友空間

          文檔技巧

          閱讀排行榜

          評(píng)論排行榜

          《Java大學(xué)教程》—第22章 多線程程序

          22.2 進(jìn)程(process):P551
          時(shí)間切片(time-slicing):處理器只是完成了一個(gè)任務(wù)的一部分工作,然后完成下一個(gè)任務(wù)的一部分工作,
          因?yàn)樘幚韰蚊看瓮瓿晒ぷ鞯臅r(shí)間都非常短,因此看起來(lái)這些任務(wù)是同時(shí)完成的。

          進(jìn)程:一個(gè)運(yùn)行的程序通常稱為一個(gè)進(jìn)程。
          并發(fā)進(jìn)程(concurrent process):兩個(gè)或多個(gè)可以同時(shí)執(zhí)行的進(jìn)程稱為并發(fā)進(jìn)程。
          在多個(gè)進(jìn)程并發(fā)執(zhí)行時(shí),每個(gè)進(jìn)程都有自己的存放程序代碼和數(shù)據(jù)的存儲(chǔ)空間,并且每個(gè)進(jìn)程的存儲(chǔ)空間對(duì)于其他進(jìn)程都是受保護(hù)的,所有這些工作都由操作系統(tǒng)完成。

          22.3    線程(thread):P552
          線程:一個(gè)程序執(zhí)行的多個(gè)獨(dú)立任務(wù)稱為線程。通常將線程稱為輕量級(jí)進(jìn)程(lightweight process),因?yàn)橐补芾磉M(jìn)程相比,管理線程需要占用較少的系統(tǒng)資源。
          線程沒(méi)有完全獨(dú)立的存儲(chǔ)空間,線程之間共享代碼區(qū)和存儲(chǔ)區(qū)。
          管理線程的方式也是基于時(shí)間切片原則,由JVM和OS協(xié)同管理。

          22.4    Thread類
          繼承Thread類實(shí)現(xiàn)線程。控制線程用三個(gè)方法:start(), run(), finish()
          主要執(zhí)行代碼在run()方法中。
          注:run()方法結(jié)束后,這個(gè)線程就運(yùn)行結(jié)束了,不可以再次調(diào)用,必須重新創(chuàng)建。原因也可參考圖22-2的狀態(tài)轉(zhuǎn)換圖,線程進(jìn)入TERMINATE狀態(tài)中,無(wú)法再次啟動(dòng)。

          22.5    線程的執(zhí)行與調(diào)度
          份額(quantum):每個(gè)進(jìn)程或者線程都可以獲得處理器上的一小段時(shí)間--稱為份額,然后輪轉(zhuǎn)到下一個(gè)進(jìn)程或線程。
          份額內(nèi)時(shí)間沒(méi)有用完時(shí),也可以使用sleep()方法,強(qiáng)制放棄CPU的占用權(quán),將CPU還給OS,從而可以繼續(xù)分配給下一個(gè)進(jìn)程或線程。
          注:sleep()方法傳入的時(shí)間間隔(以毫秒為單位),可能會(huì)拋出InterruptedException異常,必須寫在try...catch代碼塊中。

          22.6    Runnable接口
          創(chuàng)建一個(gè)實(shí)現(xiàn)Runnable接口的類,然后將類的實(shí)例作為Runnable接口的參數(shù)傳入Thread對(duì)象的構(gòu)造函數(shù)中。
          后面的工作主要就是操作Thread的對(duì)象,與前面擴(kuò)展Thread類的方法一樣了。
          注:此處的Thread對(duì)象是獨(dú)立創(chuàng)建的,前面是對(duì)Thread類的繼承。

          22.7    線程同步:P562
          異步行為(asynchronous behaviour):
              在一般情況下兩個(gè)或多個(gè)并發(fā)執(zhí)行線程的行為并不是協(xié)同的,而且無(wú)法預(yù)知在某個(gè)時(shí)間段內(nèi)哪個(gè)線程將會(huì)占用CPU,這種非協(xié)同的行為稱為異步行為。
          互斥訪問(wèn)(mutual exclusion):需要將訪問(wèn)緩沖區(qū)的程序段看作臨界區(qū)(critical section)--即在任何時(shí)刻只能被一個(gè)進(jìn)程訪問(wèn)的區(qū)域,實(shí)現(xiàn)臨界區(qū)的方式稱為互斥訪問(wèn)。
          忙等待(busy waiting):被某個(gè)線程執(zhí)行的方法循環(huán)中反復(fù)執(zhí)行,直到滿足某個(gè)條件才能終止。效率太低,可以使用wait()方法將線程掛起,直到被其他線程的消息喚醒。
          在Java中創(chuàng)建一個(gè)monitor對(duì)象(監(jiān)視器),monitor類的所有方法在任何時(shí)刻都只能被一個(gè)線程訪問(wèn)。
          可以在方法的頭部使用synchronized修飾符,由于方法被同步(synchronized),所以一旦有某個(gè)對(duì)象調(diào)用該方法,那么該方法將被置上一個(gè)鎖(lock),
          其他對(duì)象必須在該方法執(zhí)行完成后才能訪問(wèn)它。
          注1:為什么要加鎖?是因?yàn)槟阌信R界區(qū),對(duì)這個(gè)臨界區(qū)加鎖才是目的。
          因此鎖的目的:當(dāng)前類(即this.靜態(tài)變量),當(dāng)前對(duì)象(即this.變量),當(dāng)前對(duì)象中創(chuàng)建的對(duì)象(即this.對(duì)象變量),外部傳入到當(dāng)前對(duì)象中的對(duì)象。

          注2:什么可以加鎖?對(duì)象,只有對(duì)象可以加鎖。
          在Java中,每一個(gè)對(duì)象都擁有一個(gè)鎖標(biāo)記(monitor),也稱為監(jiān)視器,多線程同時(shí)訪問(wèn)某個(gè)對(duì)象時(shí),線程只有獲取了該對(duì)象的鎖才能訪問(wèn)。
          JVM會(huì)記錄并且監(jiān)管這個(gè)鎖,當(dāng)線程獲取鎖后計(jì)數(shù)器由0變1,線程若訪問(wèn)同樣鎖的其他方法,計(jì)數(shù)器還會(huì)繼續(xù)增加,從而保證線程完全釋放這個(gè)鎖后才會(huì)允許其他線程訪問(wèn)。
          所以基本數(shù)據(jù)類型的變量是不能作為臨界區(qū)的,也就不能被加鎖。

          注3:怎么樣加鎖?使用synchronized對(duì)靜態(tài)方法、方法、對(duì)象變量加鎖。
          static synchronized aStaticMethod(){...}        //        “當(dāng)前類(即this.靜態(tài)變量)”加鎖
          synchronized aMethod(){...}        //        “當(dāng)前對(duì)象(即this.變量)”加鎖
          synchronized (aObjectVariable){...}        //        “當(dāng)前對(duì)象中創(chuàng)建的對(duì)象(即this.對(duì)象變量)”或“外部傳入到當(dāng)前對(duì)象中的對(duì)象”加鎖。

          22.8    線程狀態(tài):P563
          狀態(tài)轉(zhuǎn)換圖:圖22-2 一個(gè)線程的狀態(tài)轉(zhuǎn)換圖
          start()啟動(dòng)一個(gè)線程-->線程進(jìn)入ready(就緒)狀態(tài)。
          dispatch()調(diào)度一個(gè)線程-->線程進(jìn)入running(運(yùn)行)狀態(tài)。
          線程運(yùn)行時(shí)間超時(shí)、yield()強(qiáng)制一個(gè)線程放棄CPU-->線程進(jìn)入ready(就緒)狀態(tài)。
          sleep()睡眠一個(gè)線程-->線程進(jìn)入sleeping(睡眠)狀態(tài)-->睡眠時(shí)間超時(shí)-->線程進(jìn)入ready(就緒)狀態(tài)。
          wait()-->線程進(jìn)入waiting(等待)狀態(tài)-->獲得其他線程notify()或notifyAll()方法通知-->線程進(jìn)入ready(就緒)狀態(tài)。
          由于等待輸入或等待外部設(shè)備可用-->線程處于blocked(阻塞)狀態(tài)-->阻塞時(shí)間超時(shí)或設(shè)備正常-->線程進(jìn)入ready(就緒)狀態(tài)。
          run()方法完成后,線程被終止。

          22.10    Timer類:調(diào)度線程
          在固定時(shí)間間隔內(nèi)生成ActionEvents對(duì)象。因此,必須將一個(gè)Timer對(duì)象關(guān)聯(lián)到一個(gè)ActionListener對(duì)象。
          只要Timer對(duì)象生成一個(gè)ActionEvent對(duì)象,都會(huì)執(zhí)行與Timer對(duì)象相關(guān)的ActionListener對(duì)象的actionPerformed()方法。

          自測(cè)題:
          1.    如何通過(guò)時(shí)間切片實(shí)現(xiàn)并發(fā):P552
          時(shí)間切片(time-slicing):處理器只是完成了一個(gè)任務(wù)的一部分工作,然后完成下一個(gè)任務(wù)的一部分工作,
          因?yàn)樘幚韰蚊看瓮瓿晒ぷ鞯臅r(shí)間都非常短,因此看起來(lái)這些任務(wù)是并發(fā)完成的。

          2.    進(jìn)程與線程的區(qū)別:P552
          每個(gè)進(jìn)程都有完全獨(dú)立的存儲(chǔ)空間,用于存放程序的代碼和數(shù)據(jù),并且每個(gè)進(jìn)程的存儲(chǔ)空間對(duì)于其他進(jìn)程都是受保護(hù)的,所有這些工作都由操作系統(tǒng)完成。
          每個(gè)線程沒(méi)有完全獨(dú)立的存儲(chǔ)空間,線程之間共享程序的代碼和數(shù)據(jù),線程的調(diào)度由JVM和操作系統(tǒng)協(xié)同完成。

          3.    異步線程執(zhí)行和同步線程執(zhí)行的區(qū)別:P562
          異步執(zhí)行線程:無(wú)法預(yù)知某個(gè)時(shí)間段內(nèi)哪個(gè)線程將會(huì)占用CPU,也無(wú)法估計(jì)程序執(zhí)行的結(jié)果。
          同步執(zhí)行線程:確保線程對(duì)于臨界區(qū)是互斥訪問(wèn)的,當(dāng)某個(gè)線程執(zhí)行同步代碼時(shí),其他線程無(wú)法再調(diào)用同步代碼,必須等待前面執(zhí)行的進(jìn)程解鎖。

          4.    臨界區(qū)和互斥的概念:P562
          訪問(wèn)緩沖區(qū)的程序段看作臨界區(qū)(critical section)--即在任何時(shí)刻只能被一個(gè)進(jìn)程訪問(wèn)的區(qū)域。
          實(shí)現(xiàn)臨界區(qū)的方式稱為互斥訪問(wèn)(mutual exclusion)。
          Jav提供了在多線程程序中實(shí)現(xiàn)互斥的機(jī)制,即每個(gè)對(duì)象都有一個(gè)monitor(監(jiān)視器),monitor類的所有方法在任何時(shí)刻都只能被一個(gè)線程訪問(wèn)。
          只需要在方法的頭部使用synchronized修飾符,由于方法被同步,所以一旦有某個(gè)對(duì)象調(diào)用該方法,那么這個(gè)方法就會(huì)被上鎖,其他對(duì)象如果同時(shí)想訪問(wèn)就必須等待。

          5.    如何在Java程序中避免忙等待:P562
          使用wait()方法將線程的執(zhí)行掛起,直到它收到另一個(gè)進(jìn)程的消息將它喚醒。就可以避免出現(xiàn)忙等待。

          6.    Threads6.java    RunThreads6.java

          編程練習(xí):代碼附件
          3.    CounterVersionFour.java    RunCounterVersion.java    CounterThread.java

          posted on 2016-10-04 16:36 zYx.Tom 閱讀(290) 評(píng)論(0)  編輯  收藏 所屬分類: 1.Java世界

          主站蜘蛛池模板: 望江县| 应城市| 巩留县| 宜阳县| 清丰县| 泰宁县| 西宁市| 利津县| 天全县| 新竹市| 双峰县| 长阳| 宁远县| 江口县| 天全县| 青龙| 林芝县| 崇文区| 兴城市| 乌拉特中旗| 驻马店市| 稻城县| 师宗县| 东安县| 获嘉县| 松滋市| 遵化市| 乌海市| 余庆县| 眉山市| 牡丹江市| 区。| 滁州市| 定安县| 晋城| 茶陵县| 体育| 夏津县| 神木县| 东山县| 临沂市|