26Java線程(下)_第1頁
26Java線程(下)_第2頁
26Java線程(下)_第3頁
26Java線程(下)_第4頁
26Java線程(下)_第5頁
已閱讀5頁,還剩19頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Java線程(下) 線程的join()方法 多線程編程 多線程共享數(shù)據(jù) 線程之間的通信線程的join方法 Thread API 包含了等待另一個線程完成的方法:join() 方法。當(dāng)調(diào)用 Thread.join() 時,調(diào)用線程將阻塞,直到被join方法加入的目標線程完成為止。 Thread.join() 通常由使用線程的程序調(diào)用,以將大問題劃分成許多小問題,每個小問題分配一個線程。當(dāng)所有的小問題都得到處理后,再調(diào)用主線程來進一步操作。join方法例子(示例12-6)JoinThread r = new JoinThread();Thread t = new Thread(r);t.start

2、();try t.join(); catch(InterruptedException e)多線程 多線程編程 多個線程來自同一個Runnable實例 多個線程使用同樣的數(shù)據(jù)和代碼 例子: Thread t1 = new Thread(object1); Thread t2 = new Thread(object1); 多線程例子(示例12-7) RunningObject ro = new RunningObject();Thread t1 = new Thread(ro,1st);Thread t2 = new Thread(ro,2nd);t1.start();t2.start(); 多

3、線程共享數(shù)據(jù)時的問題 經(jīng)典的銀行取款問題 有一個銀行賬戶,還有余額1100元,現(xiàn)在A通過銀行卡從中取1000元,而同時另外一個人B通過存折也從這個賬戶中取1000元。取錢之前,要首先進行判斷:如果賬戶中的余額大于要取的金額,則可以執(zhí)行取款操作,否則,將拒絕取款。 我們假定有兩個線程來分別從銀行卡和存折進行取款操作,當(dāng)A線程執(zhí)行完判斷語句后,獲得了當(dāng)前賬戶中的余額數(shù)(1000元),因為余額大于取款金額,所以準備執(zhí)行取錢操作(從賬戶中減去1000元),但此時它被線程B打斷,然后,線程B根據(jù)余額,從中取出1000元,然后,將賬戶里面的余額減去1000元,然后,返回執(zhí)行線程A的動作,這個線程將從上次中

4、斷的地方開始執(zhí)行:也就是說,它將不再判斷賬戶中的余額,而是直接將上次中斷之前獲得的余額減去1000。此時,經(jīng)過兩次的取款操作,賬戶中的余額為100元,從賬面上來看,銀行支出了1000元,但實際上,銀行支出了2000元。共享數(shù)據(jù)出錯例子 堆棧是這樣的數(shù)據(jù)結(jié)構(gòu):它是一個用于存放數(shù)據(jù)的隊列,最先進入的元素最后一個被釋放(后進先出)。用 push() 方法可以把一個元素添加到堆棧頂(稱為壓棧),用不指定索引的 pop() 方法可以把一個元素從堆棧頂釋放出來(稱為出?;驈棗#┏鰲簵9蚕頂?shù)據(jù)出錯例子(con.) 以一個數(shù)組來模擬堆棧(Stack)的操作:一個方法向堆棧里壓(push in)數(shù)據(jù),一個方法

5、向外彈出(pop out)數(shù)據(jù),下面是一個用int類型的數(shù)組來模擬的堆棧:public interface StackInterfacepublic void push(int n);public int pop();共享數(shù)據(jù)出錯例子(示例12-8)public class UnsafeStack implements StackInterface private int top = 0; private int values = new int10; public void push(int n) valuestop = n;/1 System.out.println(壓入數(shù)字+n+步驟1完

6、成); top+;/2 System.out.println(壓入數(shù)字完成); public int pop() System.out.print(彈出); top-;/3 int test = valuestop,top;/4 return test; 共享數(shù)據(jù)出錯例子(con.)public class TestUnsafeStackpublic static void main(String args)UnsafeStack s = new UnsafeStack();s.push(1);/5s.push(2);/6PushThread r1 = new PushThread(s);Po

7、pThread r2 = new PopThread(s);Thread t1 = new Thread(r1);Thread t2 = new Thread(r2);t1.start(); /7t2.start(); /8共享數(shù)據(jù)出錯例子(con.) 語句5:1 /top=1 語句6:12 /top=2 語句7:啟動壓棧(push)線程t1 語句8:啟動出棧(pop)線程t2 語句1:1215 /top=2 語句2:1215 /top=3 語句3:1215 /top=2 語句4:12 /top=2共享數(shù)據(jù)出錯例子(con.) 語句5:1 /top=1 語句6:12 /top=2 語句7:啟動

8、壓棧(push)線程t1 語句8:啟動出棧(pop)線程t2 語句1:1215 /top=2 語句3:1215 /top=1 語句4:115 /top=1 語句2:115 /top=2互斥鎖 在Java語言中,引入了對象互斥鎖(mutual exclusive lock,也簡稱為對象鎖)的概念,來保證共享數(shù)據(jù)操作的完整性: 每個對象都對應(yīng)于一個可稱為“互斥鎖”的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。 關(guān)鍵字synchronized 來與對象的互斥鎖聯(lián)系。當(dāng)某個對象用synchronized修飾時,表明該對象在任一時刻只能由一個線程訪問。關(guān)鍵字synchronized 在J

9、ava中的兩種使用synchronized的方式: 放在方法前面,這樣,調(diào)用該方法的線程均將獲得對象的鎖。 放在代碼塊前面,它也有兩種形式: synchronized (this) 或synchronized :代碼塊中的代碼將獲得當(dāng)前對象引用的鎖 synchronized(otherObj) :代碼塊中的代碼將獲得指定對象引用的鎖釋放鎖 如果一個線程一直占用一個對象的鎖,則其他的線程將永遠無法訪問該對象,因此,需要在適當(dāng)?shù)臅r候,將對象鎖歸還。 當(dāng)線程執(zhí)行到synchronized()塊結(jié)束時,釋放對象鎖。 當(dāng)在synchronized()塊中遇到break, return或拋出excepti

10、on,則自動釋放對象鎖。 當(dāng)一個線程調(diào)用wait()方法時,它放棄擁有的對象鎖并進入等待隊列。synchronized例子(示例12-8) public void push(int n) synchronized(this) valuestop = n; System.out.println(壓入數(shù)字+n+步驟1完成); top+; System.out.println(壓入數(shù)字完成); public int pop() synchronized(this) System.out.print(彈出); top-; int test = valuestop,top; return test; 死

11、鎖 是指兩個線程,都相互等待對方釋放lock 是不可測知或避開的 應(yīng)采取措施避免死鎖的出現(xiàn)對象的wait()、notify()和notifyAll()方法 Object 類定義了 wait()、notify() 和 notifyAll() 方法。可以讓線程相互通知事件的發(fā)生。要執(zhí)行這些方法,必須擁有相關(guān)對象的鎖。 wait() 會讓調(diào)用線程休眠,直到用 Terrupt() 中斷它、過了指定的時間、或者另一個線程用 notify() 或 notifyAll() 喚醒它。 當(dāng)對某個對象調(diào)用 notify() 時,如果有任何線程正在通過 wait() 等待該對象,那么就會喚醒其中一

12、個線程。當(dāng)對某個對象調(diào)用 notifyAll() 時,會喚醒所有正在等待該對象的線程。實現(xiàn)了線程通信的堆棧類(示例12-9) public void push(int n) synchronized(this) while(dataAvailable) /1 try wait(); catch(InterruptedException e) /忽略 /2 valuestop = n; System.out.println(壓入數(shù)字+n+步驟1完成); top+; dataAvailable = true; notifyAll(); System.out.println(壓入數(shù)字完成); 實現(xiàn)了

13、線程間通信的堆棧類(con.) public int pop() synchronized(this) while(!dataAvailable) /3 try wait(); catch(InterruptedException e) /忽略 /4 System.out.print(彈出); top-; int test = valuestop,top; dataAvailable = false; notifyAll(); return test; 避免無謂的同步方法 因為同步會降低程序的執(zhí)行效率,所以應(yīng)該避免無謂的同步 通過所謂的Fine-Grained鎖的機制,可以避免這種情況多線程編

14、程一般規(guī)則 如果兩個或兩個以上的線程都修改一個對象,那么把執(zhí)行修改的方法定義為被同步的,如果對象更新影響到只讀方法,那么只讀方法也要定義成同步的。 不要濫用同步。如果在一個對象內(nèi)的不同的方法訪問的不是同一個數(shù)據(jù),就不要將方法設(shè)置為synchronized的。 如果一個線程必須等待一個對象狀態(tài)發(fā)生變化,那么他應(yīng)該在對象內(nèi)部等待,而不是在外部。他可以通過調(diào)用一個被同步的方法,并讓這個方法調(diào)用wait()。 每當(dāng)一個方法返回某個對象的鎖時,它應(yīng)當(dāng)調(diào)用notifyAll()來讓等待隊列中的其他線程有機會執(zhí)行。 記住wait()和notify()/notifyAll()是Object類方法,而不是Thread類的方法。仔細查看每次調(diào)用wait()方法,都有相應(yīng)的notify()/notifyAll()方法,且它們均作用于同一個對象。多線程編程一般規(guī)則

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論