9--黑馬程式設計師--技術總結之多執行緒
、期待與您交流! ----------------------
一.多執行緒的概念
以往開發的程式大多是單執行緒的,即一個程式只有一條從頭至尾的執行線索。然而現實世界中的很多過程都具有多條線索同時動作的特性:例如,我們可以一邊看電視,一邊活動胳膊,如果不容許這樣做,我們會感覺很難受。再如一個網路伺服器可能需要同時處理多個客戶機的請求等。
Java的一大特性點就是內建對多執行緒的支援。多執行緒是指同時存在幾個執行體,按幾條不同的執行線索共同工作的情況,它使得程式設計人員可以很方便地開發出具有多執行緒功能,能同時處理多個任務的功能強大的應用程式。雖然執行執行緒給人一種幾個事件同時發生的感覺,但這只是一種錯覺,因為計算機在任何給定的時刻只能執行那些執行緒中的一個。為了建立這些執行緒正在同步執行的感覺,Java快速地把控制從一個執行緒切換到另一個執行緒。
觀察下列程式碼:
- <spanstyle="font-size:12px;"> public static void main(String[] args) {
- // TODO Auto-generated method stub
- while(true) {
- System.out.println("JAVA");
- }
- while(true) {
- System.out.println("C++");
- }
-
}</
上述程式碼是有問題的,因為第二個while語句是永遠沒有機會執行的程式碼。如果能在程式中建立兩個執行緒,每個執行緒分別執行一個while迴圈,那麼兩個迴圈就都有機會執行,即一個執行緒中的while語句執行一段時間後,就會輪到另一個執行緒中的while語句執行一段時間,這是因為Java虛擬機器(JVM)負責管理這些執行緒,這CPU將被輪流執行,使得每個執行緒有機會使用CPU資源.
1.執行緒與程序
程序是程式的一次動態執行過程,它對應了從程式碼載入、執行至執行完畢的一個完整過程,這個過程也是程序本身從產生、發展至消亡的過程。執行緒是比程序更小的執行單位。一個程序在其執行過程中,可以產生多個執行緒,形成多條執行線索,每條線索,即每個執行緒也有它自身的產生、存在和消亡的過程,也是一個動態的概念。每個程序都有一段專用的記憶體區域,與此不同的是,執行緒間可以共享相同的記憶體單元(包括程式碼與資料),並利用這些共享單元來實現資料交換、實時通訊與必要的同步操作。多執行緒的程式能更好地表達和解決現實世界的具體問題,是計算機應用開發和程式設計的一個必然發展趨勢。
每個Java程式都有一個預設的主執行緒。Java應用程式總是從主類的main方法開始執行。當JVM載入程式碼,發現main方法之後,就會啟動一個執行緒,這個執行緒稱作“主執行緒”,該執行緒負責執行main方法。在main方法的執行中再建立的執行緒,就稱為程式中的其他執行緒。如果main方法中沒有建立其他的執行緒,那麼當main方法執行完最後一個語句,即main方法返回時,JVM就會結束Java應用程式。如果main方法中又建立了其他執行緒,那麼JVM就要在主執行緒和其他執行緒之間輪流切換,保證每個執行緒都有機會使用CPU資源,main方法即使執行完最後的語句,JVM也不會結束程式,JVM一直要等到程式中的所有執行緒都結束之後,才結束Java應用程式。
2.執行緒的狀態與生命週期
Java使用Thread類及其子類的物件來表示執行緒,新建的執行緒在它的一個完整的生命週期中通常要經歷如下的4種狀態。
(1)新建
當一個Thread類或其子類的物件被宣告並建立時,新生的執行緒物件處於新建狀態。此時它已經有了相應的記憶體空間和其他資源。
(2)執行
執行緒建立之後就具備了執行的條件,一旦輪到它來享用CPU資源時,即JVM將CPU的使用權切換給該執行緒時,此執行緒就可以脫離建立它的主執行緒,獨立開始自己的生命週期了。
執行緒建立後僅僅是佔有了記憶體資源,在JVM管理的執行緒中還沒有這個執行緒,此執行緒必須呼叫startO方法(從父類繼承的方法)通知JVM,這樣JVM就會知道又有一個新執行緒捧隊等候切換了。
當JVM將CPU的使用權切換給執行緒時,如果執行緒是Thread的子類建立的,該類中run方法就立刻執行。所以必須在子類中重寫父類的run方法,Thread類中的run方法沒有具體內容,程式要在Thread類的子類中重寫run方法來覆蓋父類的run方法,run方法規定了該執行緒的具體使命。線上程沒有結束run0方法之前,不要讓執行緒再呼叫start0方法,否則將發生ILLegalThreadStateException異常。
(3)中斷
有4種原因的中斷:
1)JVM將CPU資源從當前執行緒切換給其他執行緒,使本執行緒讓出CPU的使用權處於中斷狀態。
2)執行緒使用CPU資源期間,執行了sleep(int millsecond)方法,使當前執行緒進入休眠狀態。slecp(int millsecond)方法是Thread類中的一個類方法,執行緒一旦執行了slecp(int millsecond)方法,就立刻讓出CPU的使用權,使當前執行緒處於中斷狀態。經過引數millsecond指定的毫秒數之後,該執行緒就重新進到執行緒佇列中捧隊等待CPU資源,以便從中斷處繼續執行。
3)執行緒使用CPU資源期間,執行了wait0方法,使得當前執行緒進入等待狀態。等待狀態的執行緒不會主動進到執行緒佇列中排隊等待CPU資源,必須由其他執行緒呼叫notify0方法通知它,使得它重新進入到執行緒佇列中排隊等待CPU資源,以便從中斷處繼續執行。有關wait()、noftify()和notifyall()方法將在本部落格後面詳細討論。
4)執行緒使用CPU資源期間,執行某個操作進入阻塞狀態,比如執行讀/寫操作引起阻塞。進入阻塞狀態時執行緒不能進入排隊佇列,只有當引起阻塞的原因消除後,執行緒才重新進入到執行緒佇列中排隊等待CPU資源,以便從原來中斷處繼續執行。
(4)死亡
處於死亡狀態的執行緒不具有繼續執行的能力。執行緒死亡的原因有二個:一個是正常執行的執行緒完成了它的全部工作,即執行完run方法中的全部語句,結束了run方法:Thread原因是執行緒被提前強制性地終止,即強制run方法結束。所謂死亡狀態就是執行緒釋放了實體,即釋放分配給執行緒物件的記憶體。現在,看一個完整的例子,通過分析執行結果闡述執行緒的4種狀態。該例子中用Thread的子類建立了兩個執行緒,模擬貓狗執行緒。
- <spanstyle="font-size:12px;">public class ThreadDemo2 {
- /**一個多執行緒例子的展示
- * @黑馬ZWF
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Cat c = new Cat(); //為貓類建立物件
- Dog d = new Dog(); //為狗類建立物件
- c.start(); //啟動多執行緒
- d.start(); //啟動多執行緒
- for(int x = 0; x <8; x++) {
- System.out.println("我是主人");
- }
- }
- }
- class Cat extends Thread {
- public void run() { //重寫run方法
- for(int x = 0; x <8; x++) {
- System.out.println("我是貓");
- }
- }
- }
- class Dog extends Thread {
- public void run() { //重寫run方法
- for(int x = 0; x <8; x++) {
- System.out.println("我是狗");
- }
- }
- }</span>
二. 執行緒建立的兩種方式:繼承Thread類和使用Runnable介面
1.利用Thread類的子類建立執行緒
其實上面的ThreadDemo2就是繼承Thread類來進行執行緒的建立。下面我們來具體介紹如何用Thread類的子類來建立物件。
在編寫Thread類的子類時,需要重寫父類的run()方法,其目的是規定執行緒的具體操作,否則執行緒就什麼也不做,因為父類的run()方法中沒有任何操作語句。
下面例子中除主執行緒外還有兩個執行緒,這兩個執行緒共享一個物件,兩個執行緒在執行期間修改這個物件的成員變數。為了使結果儘量不依賴於當前CPU資源的使用情況。應當讓執行緒主動呼叫sleep方法讓出CPU的使用權進入中斷狀態,sleep方法是Thread類的靜查布法,執行緒在佔用CPU資源期間,通過呼叫sleep方法來使自己最棄CPU資源,休眠一段時間。程式碼示例如下:
- public class ThreadDemo3 {
- /**用Thread類的子類建立程序
- * @黑馬ZWF
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- ComputerSum sum = new ComputerSum();
- People teacher = new People("老師", 200, sum);
- People student = new People("學生", 200, sum);
- teacher.start() ;
- student.start() ;
- }
- }
- class ComputerSum {
- int sum;
- public void setSum(int n) {
- sum = n;
- }
- public int getSum() {
- return sum;
- }
- }
- class People extends Thread {
- int timeLength; //執行緒休眠的時間長度
- ComputerSum sum;
- People(String name, int timeLength, ComputerSum sum) {
- setName(name); //呼叫Thread類的方法setName為執行緒起個名字
- this.timeLength = timeLength;
- this.sum = sum;
- }
- public void run() {
- for(int i = 1; i <= 5; i++) {
- int m = sum.getSum();
- sum.setSum(m + 1);
- System.out.println("我是" + getName() +",現在的和:" + sum.getSum());
- try {
- sleep(timeLength);
- }
- catch(InterruptedException e){
- System.out.println("發生InterruptedException異常");
- }
- }
- }
- }
執行結果如下:
2.使用Runnable介面建立程序(推薦)
使用Thread子類建立執行緒的優點是:可以在子類中增加新的成員變數,使執行緒具有某種屬性,也可以在子類中新增加方法,使執行緒具有某種功能。但是,Java不支援多繼承,Thread類的子類不能再擴充套件其他的類。但是使用Runnable介面的話,就可以實現擴充套件,提高程式碼的靈活性。
1)Runnable介面與目標物件
建立執行緒的另一個途徑就是用Thread類直接建立執行緒物件。使用Thread建立執行緒物件時,通常使用的構造方法是:
thread(Runnable target)
該構造方法中的引數是一個Runnable型別的介面,因此,在建立執行緒物件時必須向構造方法的引數傳遞一個實現Runnable介面類的例項,該例項物件稱作所創執行緒的目標物件,當執行緒呼叫start()方法後,一旦輪到它來享用CPU資源,目標物件就會自動呼叫介面中的run()方法(介面回撥),這一過程是自動實現的,使用者程式只需要讓執行緒呼叫start()方法即可,也就是說,當執行緒被排程並轉入執行狀態時,所執行的就是run()方法中所規定的操作。
執行緒間可以共享相同的記憶體單元(包括程式碼與資料),並利用這些共享單元來實現資料交換、實時通訊與必要的同步操作。對於Thread(Runnable target)杓造方法建立的執行緒,輪到它來享用CPU資源時,目標物件就會自動呼叫介面中的run()方法,因此,對於使用同一目標物件的執行緒,目標物件的成員變數自然就是這些執行緒共亨的資料單元。另外,建立目標物件類在必要時還可以是某個特定類的子類,因此,使用Runnable介面比使用Thread類的子類更具有靈活性.下面程式碼示例是Runnable介面建立多執行緒的展示,改動自ThreadDemo2.
- public class ThreadDemo4 {
- /**Runnable介面建立多執行緒的展示,改動自ThreadDemo2
- * @黑馬ZWF
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Cat c = new Cat();
- Dog d = new Dog();
- Thread t1 = new Thread(c); //使用Runnable介面的建立方法
- Thread t2 = new Thread(d);
- t1.start(); //啟動多執行緒t1
- t2.start(); //啟動多執行緒t2
- }
- }
- class Cat implements Runnable {
- public void run() { //重寫run方法
- for(int x = 0; x <8; x++) {
-
相關推薦
9--黑馬程式設計師--技術總結之多執行緒
、期待與您交流! ---------------------- 一.多執行緒的概念 以往開發的程式大多是單執行緒的,即一個程式只有一條從頭至尾的執行線索。然而現實世界中的很多過程都具有多條線索同時動作的特性:例如,我們可以一邊看電視,一邊活動胳膊,如果
黑馬程式設計師----Java基礎之多執行緒
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g
黑馬程式設計師--Java基礎之多執行緒
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">j
黑馬程式設計師——java基礎之多執行緒
---------------------- ASP.Net+Android+IOS開發、.Net培訓、期待與您交流! ---------------------- 1. Java 多執行緒程式設計 Java 語言的優勢之一就是執行緒處理較為簡單。 一般
8--黑馬程式設計師---技術總結之抽象類、內部類
、期待與您交流! ---------------------- 一.抽象類 1.抽象類的概念 在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有 包含足夠的資訊來描繪一個具體的物
7--黑馬程式設計師--技術總結之幾個重要的關鍵字
、期待與您交流! ---------------------- 一.static關鍵字 static表示“全域性”或者“靜態”的意思,用來修飾成員變數和成員方法,也可以形成靜態static程式碼塊,但是Java語言中沒有全域性變數的概念。
5--黑馬程式設計師--技術總結之面向物件
、期待與您交流! ---------------------- 一.什麼是面向物件? 1.面向物件的定義 面向物件是一種對現實世界理解和抽象的方法,是計算機程式設計技術發展到一定階段後的產物。早期的計算機程式設計是基於面向過程
4--黑馬程式設計師--技術總結之陣列
<span style="white-space: pre; color: rgb(68, 68, 68); font-family: 'Microsoft Yahei', 微軟雅黑, Tahoma, Arial, Helvetica, STHeiti; font-
黑馬程式設計師——方法總結之網編
------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ------- /* 1.IP地址類 InetAddress 所在包:java.net.InetAddress
15個頂級Java多執行緒面試題及回答 / Java程式設計師面試中的多執行緒問題
http://wenku.baidu.com/link?url=-7RVShQCzkHaRbyPdGP-oeVXgZ7t4mS2oqXevpzweesI_Heof5zqc_Wsvhhi8pZSU7xQWEp6e_XO7ch5nWaU_-x9Ja0CN_5V3K6QNl
『黑馬程式設計師』---java--深入加強--執行緒併發庫
----------- android培訓、java培訓、java學習型技術部落格、期待與您交流! ------------ 孝祥老師Java5執行緒併發庫講解---截圖示記筆記 java.util.concurrent.atomic 類 AtomicInteger
黑馬程式設計師_基礎加強_Java執行緒通訊和執行緒併發庫
------- android培訓、java培訓、期待與您交流! ---------- java5的執行緒鎖技術 Lock&Condition實現執行緒同步通訊 Lock比傳統的synchronized方式更加面向物件,兩個執行緒執行的程式碼塊要實現同步互斥,
黑馬程式設計師----Java基礎之面向物件(封裝 繼承 多型)(二)
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g
黑馬程式設計師----Java基礎之面向物件(封裝 繼承 多型)
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g
黑馬程式設計師技術部落格之哲學家吃飯問題
----------- android培訓、java培訓、java學習型技術部落格、期待與您交流! ------------ 哲學家就餐:有五個哲學家繞著圓桌坐,每個哲學家面前有一碗麵,兩人之間有一支筷子,這樣每個哲學家左右各有一支筷子。哲學家有2個狀態,思考或者拿起筷子吃
黑馬程式設計師——java基礎拾遺之多執行緒(二) 執行緒同步、執行緒通訊
執行緒安全的概念:當多個執行緒同時執行一段程式碼時,如果結果和單執行緒執行時一致,而且其他變數也和預期的一致,說明是這段程式碼是執行緒安全的。但是,多執行緒執行的過程中會出現單執行緒時候不會出現的問題,大多出現在多個執行緒同時操作全域性變數或者靜態變數的時候。當出現這種
黑馬程式設計師——Java高新技術之反射學習總結一
反射學習總結 基礎補充: Java程式中的各個Java類屬於同一類事務,描述這類事務的Java類名就是C
黑馬程式設計師 java程式設計之面向物件學習筆記總結
---------------------- ASP.Net+Unity開發、.Net培訓、期待與您交流! ---------------------- 繼承: 在java中,在我們要對一個事物進行封裝時,發現有某一個類的特性和要封裝的這個 類的特性相同,而我們可以在這個
黑馬程式設計師之多執行緒二
---------------------- Windows Phone 7手機開發、.Net培訓、期待與您交流! ---------------------- Thread類幾個重要的方法: Start():啟動執行緒; Sleep(int):靜態方法,暫停當前執行緒指定
黑馬程式設計師----Java基礎之反射
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g