Java語言程序設(shè)計第8章課件_第1頁
Java語言程序設(shè)計第8章課件_第2頁
Java語言程序設(shè)計第8章課件_第3頁
Java語言程序設(shè)計第8章課件_第4頁
Java語言程序設(shè)計第8章課件_第5頁
已閱讀5頁,還剩40頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第8章 線程鄭 莉JAVA語言程序設(shè)計1第8章 線程鄭 莉JAVA語言程序設(shè)計1本講內(nèi)容線程基礎(chǔ)線程的概念Thread類Runnable接口資源共享和線程同步線程間的通信線程的生命周期線程的優(yōu)先級程序舉例2本講內(nèi)容線程基礎(chǔ)2線程的概念進(jìn)程:程序的一次執(zhí)行線程:一個進(jìn)程中的多個控制流通過多線程,一個進(jìn)程表面上看同時可以執(zhí)行一個以上的任務(wù)并發(fā)多數(shù)程序設(shè)計語言不支持并發(fā),支持多線程要借助于操作系統(tǒng)“原語(primitives)”Java是第一個支持內(nèi)置線程操作的主流編程語言線 程 基 礎(chǔ)3線程的概念進(jìn)程:程序的一次執(zhí)行線 程 基 礎(chǔ)3Thread類簡介線程類需要繼承Thread類Thread 的構(gòu)造

2、函數(shù)public Thread( String threadName )public Thread()在線程的run方法中編寫線程的主要任務(wù)sleep 方法使線程休眠interrupt 方法中斷一個運行中的線程 isAlive方法檢查線程的狀態(tài)setName方法設(shè)置線程名join方法等待線程結(jié)束,以執(zhí)行當(dāng)前線程線 程 基 礎(chǔ)4Thread類簡介線程類需要繼承Thread類線 程 基 礎(chǔ)例8_1 在新線程中計算整數(shù)的階乘public class Ex8_1 public static void main( String args ) System.out.println(main thread

3、starts); FactorialThread thread= new FactorialThread(10); thread.start(); System.out.println( new thread started,main thread ends ); / end main 線 程 基 礎(chǔ)5例8_1 在新線程中計算整數(shù)的階乘public class/ class FactorialThread controls thread executionclass FactorialThread extends Thread private int num; public Factorial

4、Thread( int num ) this.num=num; public void run() int i=num; int result=1; while(i0) result=result*i; i=i-1; System.out.println(The factorial of +num+ is +result); System.out.println(new thread ends); 6/ class FactorialThread contr運行結(jié)果如下:main thread startsnew thread started,main thread endsThe facto

5、rial of 10 is 3628800new thread ends7運行結(jié)果如下:7例8_2 創(chuàng)建3個新線程,每個線程睡眠任意0-6秒鐘,然后結(jié)束。public class Ex8_2 public static void main( String args ) /創(chuàng)建并命名每個線程 TestThread thread1 = new TestThread( thread1 ); TestThread thread2 = new TestThread( thread2 ); TestThread thread3 = new TestThread( thread3 ); System.out

6、.println( Starting threads ); thread1.start(); / 啟動線程1 thread2.start(); / 啟動線程2 thread3.start(); / 啟動線程3 System.out.println( Threads started, main endsn ); 線 程 基 礎(chǔ)8例8_2 創(chuàng)建3個新線程,每個線程睡眠任意0-6秒鐘,然后結(jié)class TestThread extends Thread private int sleepTime; public TestThread( String name )/構(gòu)造函數(shù) super( name )

7、; /調(diào)用基類構(gòu)造函數(shù)為線程命名 /獲得隨機休息毫秒數(shù) sleepTime = ( int ) ( Math.random() * 6000 ); public void run() /線程啟動并開始運行后要執(zhí)行的方法 try System.out.println( getName() + going to sleep for + sleepTime ); Thread.sleep( sleepTime ); /線程休眠 catch ( InterruptedException exception ) ; /運行結(jié)束,給出提示信息 System.out.println( getName() +

8、 finished ); 9class TestThread extends Threa運行結(jié)果為:Starting threadsThreads started, main endsthread1 going to sleep for 3519thread2 going to sleep for 1689thread3 going to sleep for 5565thread2 finishedthread1 finishedthread3 finished10運行結(jié)果為:10Runnable接口如果希望一個已經(jīng)有基類的類支持多線程,則不能再繼承Thread類了(Java不支持多繼承)解決

9、方法:使類實現(xiàn)Runnable接口,再與Thread類結(jié)合使用一個內(nèi)部類提供Runnable的實現(xiàn)代碼,將內(nèi)部類的對象與Thread結(jié)合相對于Thread類,它更適合于多個線程處理同一資源線 程 基 礎(chǔ)11Runnable接口如果希望一個已經(jīng)有基類的類支持多線程,則例8_3 使用Runnable接口實現(xiàn)例8_1功能public class Ex8_1 public static void main( String args ) System.out.println(main thread starts); FactorialThread t=new FactorialThread(10); n

10、ew Thread(t).start(); System.out.println( new thread started,main thread ends ); / end main 線 程 基 礎(chǔ)12例8_3 使用Runnable接口實現(xiàn)例8_1功能publi/ class FactorialThread controls thread executionclass FactorialThread implements Runnable private int num; public FactorialThread( int num ) this.num=num; public void r

11、un() int i=num; int result=1; while(i0) result=result*i; i=i-1; System.out.println(The factorial of +num+ is +result); System.out.println(new thread ends); 13/ class FactorialThread contr例8_4 使用Runnable接口實現(xiàn)例8_2功能public class Ex8_4 public static void main( String args ) /創(chuàng)建3個實現(xiàn)Runnable接口類的對象 TestThre

12、ad thread1 = new TestThread(); TestThread thread2 = new TestThread(); TestThread thread3 = new TestThread(); System.out.println( Starting threads ); /分別以三個對象為參數(shù)創(chuàng)建三個新線程, /第二個參數(shù)為新線程命名并啟動之 new Thread(thread1,Thread1).start(); new Thread(thread2,Thread2).start(); new Thread(thread3,Thread3).start(); Sys

13、tem.out.println( Threads started, main endsn ); 線 程 基 礎(chǔ)14例8_4 使用Runnable接口實現(xiàn)例8_2功能publiclass TestThread implements Runnable private int sleepTime; public TestThread() /構(gòu)造方法 /獲得隨機休息毫秒數(shù) sleepTime = ( int ) ( Math.random() * 6000 ); public void run() /線程啟動并開始運行后要執(zhí)行的方法 try System.out.println( Thread.cur

14、rentThread().getName() + going to sleep for + sleepTime ); Thread.sleep( sleepTime ); /線程休眠 catch ( InterruptedException exception ) ; /運行結(jié)束,給出提示信息 System.out.println( Thread.currentThread().getName() + finished ); 15class TestThread implements Ru運行結(jié)果如下:Starting threadsThread1 going to sleep for 148

15、7Thread2 going to sleep for 1133Threads started, main endsThread3 going to sleep for 2328Thread2 finishedThread1 finishedThread3 finished16運行結(jié)果如下:16資源共享和線程同步獨立的同時運行的線程有時需要共享一些數(shù)據(jù)并且考慮到彼此的狀態(tài)和動作。例如生產(chǎn)/消費問題:生產(chǎn)線程產(chǎn)生數(shù)據(jù)流,然后這些數(shù)據(jù)流再被消費線程消費。具體來說,假設(shè)一個Java應(yīng)用程序,其中有一個線程負(fù)責(zé)往文件寫數(shù)據(jù),另一個線程從同一個文件中往出都數(shù)據(jù),因為涉及到同一個資源,這里是同一個文件,這

16、兩個線程必須保證某種方式的同步。當(dāng)多個線程的執(zhí)行代碼來自同一個類的實例(若干個)時,即稱它們共享相同的代碼,當(dāng)共享訪問相同的對象時,即它們共享相同的數(shù)據(jù)。使用Runnable接口可以輕松實現(xiàn)多個線程共享相同數(shù)據(jù),只要用同一個實現(xiàn)了Runnable接口的實例作為參數(shù)創(chuàng)建多個線程就可以了。線 程 基 礎(chǔ)17資源共享和線程同步獨立的同時運行的線程有時需要共享一些數(shù)據(jù)并例8_5 修改例8_4/只用一個Runnable類型的對象為參數(shù)創(chuàng)建3個新線程。public class Ex8_5 public static void main( String args ) /只創(chuàng)建1個實現(xiàn)Runnable接口類的

17、對象 TestThread thread = new TestThread(); System.out.println( Starting threads ); /只用一個Runnable類型對象為參數(shù)創(chuàng)建三個新線程, /命名并啟動之 new Thread(thread,Thread1).start(); new Thread(thread,Thread2).start(); new Thread(thread,Thread3).start(); System.out.println( Threads started, main endsn ); 線 程 基 礎(chǔ)18例8_5 修改例8_4/只用

18、一個Runnable類型的對象class TestThread implements Runnable private int sleepTime; public TestThread()/構(gòu)造函數(shù) /獲得隨機休息毫秒數(shù) sleepTime = ( int ) ( Math.random() * 6000 ); public void run() /線程啟動并開始運行后要執(zhí)行的方法 try System.out.println( Thread.currentThread().getName() + going to sleep for + sleepTime ); Thread.sleep(

19、sleepTime ); /線程休眠 catch ( InterruptedException exception ) ; /運行結(jié)束,給出提示信息 System.out.println( Thread.currentThread().getName() + finished ); 19class TestThread implements RuStarting threadsThread1 going to sleep for 966Thread2 going to sleep for 966Threads started, main endsThread3 going to sleep f

20、or 966Thread1 finishedThread2 finishedThread3 finished20Starting threads20例8_6 用三個線程模擬三個售票口,總共出售200張票。public class Ex8_6public static void main(String args) /新建一個售票類的對象SellTickets t=new SellTickets(); /用此對象作為參數(shù)創(chuàng)建3個新線程并啟動new Thread(t).start(); new Thread(t).start();new Thread(t).start();線 程 基 礎(chǔ)21例8_6

21、 用三個線程模擬三個售票口,總共出售200張票。puclass SellTickets implements Runnable /將共享的資源作為私有變量 private int tickets=200; public void run() while(tickets0) /直到?jīng)]有票可售為止 System.out.println( Thread.currentThread().getName() + is selling ticket +tickets-); 22class SellTickets implements R例8_7 用兩個線程模擬存票、賣票過程public class Ex8

22、_7public static void main(String args) /新建一個票類對象,總票數(shù)作為參數(shù) Tickets t=new Tickets(10); /以票類對象為參數(shù)創(chuàng)建存票線程對象,并啟動 new Producer(t).start(); /以同一個票類對象為參數(shù)創(chuàng)建售票線程,并啟動 new Consumer(t).start(); 線 程 基 礎(chǔ)23例8_7 用兩個線程模擬存票、賣票過程public clasclass Tickets /票類int number=0; /票號int size; /總票數(shù) /表示目前是否有票可售boolean available=fals

23、e; /構(gòu)造方法,傳入總票數(shù)參數(shù) public Tickets(int size)this.size=size; 24class Tickets /票類24class Producer extends Thread /存票線程Tickets t=null;public Producer(Tickets t) /構(gòu)造函數(shù)以一個票類對象為參數(shù) this.t=t; public void run() /限制循環(huán)條件為存票序號小于總票數(shù) while(t.number)t.size) System.out.println(Producer puts ticket +(+t.number); t.avai

24、lable=true; /可以賣票 25class Producer extends Thread class Consumer extends Thread /售票線程Tickets t=null;int i=0;public Consumer(Tickets t) /構(gòu)造函數(shù)以一個票類對象為參數(shù) this.t=t;public void run() while(it.size) /循環(huán)條件為售票序號小于總票數(shù) if(t.available=true & i=t.number) /有票且小于目前票序號 System.out.println(Consumer buys ticket +(+i)

25、;if(i=t.number) /如果票已售到當(dāng)前序號,則不可售 t.available=false; 26class Consumer extends Thread 運行結(jié)果Producer puts ticket 1Producer puts ticket 2Producer puts ticket 3Producer puts ticket 4Producer puts ticket 5Producer puts ticket 6Producer puts ticket 7Producer puts ticket 8Consumer buys ticket 1Consumer buys

26、ticket 2Consumer buys ticket 3Consumer buys ticket 4Consumer buys ticket 5Consumer buys ticket 6Consumer buys ticket 7Consumer buys ticket 8Producer puts ticket 9Producer puts ticket 10死機(進(jìn)入死循環(huán))27運行結(jié)果27錯誤原因假如售票線程運行到t.available=false之前,CPU切換到執(zhí)行存票線程,存票線程將available置為true,但再次切換到售票線程后,售票線程執(zhí)行t.available=f

27、alse,則由于售票號目前還是8,小于總票數(shù),且存票線程已經(jīng)結(jié)束不再能將t.available置為true,則售票線程陷入了死循環(huán)。線 程 基 礎(chǔ)28錯誤原因假如售票線程運行到t.available=false線程同步(Synchronization)Java 使用的同步機制是監(jiān)視器,支持線程的互斥與同步互斥:許多線程在同一個共享數(shù)據(jù)上操作而互不干擾,同一時刻只能有一個線程訪問該共享數(shù)據(jù)。因此有些方法或程序段在同一時刻只能被一個線程執(zhí)行,稱之為監(jiān)視區(qū)。協(xié)作:多個線程可以有條件地同時操作共享數(shù)據(jù)執(zhí)行監(jiān)視區(qū)代碼的線程在條件滿足的情況下可以允許其它線程進(jìn)入監(jiān)視區(qū)。線 程 基 礎(chǔ)29線程同步(Sync

28、hronization)Java 使用的同線程間的通信線程同步關(guān)鍵字synchronized用于指定需要同步的代碼段或方法,也就是監(jiān)視區(qū)。wait() 當(dāng)前狀態(tài)不適合本線程執(zhí)行時,進(jìn)入等待狀態(tài)notify()隨機喚醒一個等待的線程,本線程繼續(xù)執(zhí)行。notifyAll()喚醒所有等待的線程,本線程繼續(xù)執(zhí)行。線 程 基 礎(chǔ)30線程間的通信線程同步關(guān)鍵字synchronized線 程線程間的通信線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,這期間關(guān)鍵數(shù)據(jù)仍可能被改變。被喚醒線程的線程可能有多個。(使用notifyAll時)。被喚醒的線程開始執(zhí)行時,一定要判斷當(dāng)前狀態(tài)是否適合自己運行。線 程 基 礎(chǔ)

29、31線程間的通信線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,例8_8 實現(xiàn)例8_7功能。將同步方法放在共享的資源類Tickets中。public class Ex8_8public static void main(String args) Tickets t=new Tickets(10); new Producer(t).start(); new Consumer(t).start();線 程 基 礎(chǔ)32例8_8 實現(xiàn)例8_7功能。將同步方法放在共享的資源類Ticclass Tickets int size; /票總數(shù) int number=0; /存票序號 int i=0; /售票序

30、號 boolean available=false; /是否有待售的票 public Tickets(int size) this.size=size; public synchronized void put() /同步代碼塊,實現(xiàn)存票的功能 System.out.println(Producer puts ticket +(+number); available=true; public synchronized void sell() /同步代碼塊,實現(xiàn)售票的功能 if(available=true & i=number) System.out.println(Consumer buys

31、 ticket +(+i); if(i=number) available=false; 33class Tickets33class Consumer extends Thread Tickets t=null; /構(gòu)造方法,使兩線程共享票類對象public Consumer(Tickets t) this.t=t; public void run() /如果售票數(shù)小于限定總量,則不斷售票 while(t.it.size)t.sell(); 34class Consumer extends Thread3例8_9 每存入一張票,就售一張票,售出后,再存入public class Ex8_8p

32、ublic static void main(String args)Tickets t=new Tickets(10);new Producer(t).start();new Consumer(t).start();線 程 基 礎(chǔ)35例8_9 每存入一張票,就售一張票,售出后,再存入publiclass Ticketsint size;int number=0;int i=0;boolean available=false;public Tickets(int size) this.size=size; public synchronized void put() if(available)

33、 /如果還有存票待售,則存票線程等待 trywait(); catch(Exception e) System.out.println(Producer puts ticket +(+number); available=true; notify();./存票后喚醒售票線程開始售票36class Tickets36public synchronized void sell() if(!available) /如果沒有存票,則售票線程等待 trywait(); catch(Exception e) if(i=number) System.out.println(Consumer buys tic

34、ket +(+i); if(i=number) try Thread.sleep(1); catch(Exception e) available=false; notify(); /售票后喚醒存票線程開始存票37public synchronized void sellclass Producer extends ThreadTickets t=null;public Producer(Tickets t)this.t=t;public void run()while(t.numbert.size)t.put();38class Producer extends Thread3class Consumer extends ThreadTickets t=null;public Consumer(Tickets t)this.t=t;public void run()while(t.it.size)t.sell();3

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論