大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 Java學習 深入淺出:Java多線程編程實戰教程(實用篇)

深入淺出:Java多線程編程實戰教程(實用篇)

更新時間:2019-09-26 10:08:58 來源:動力節點 瀏覽4123次



image.png

  一、進程和線程概念


  在開始java線程的學習前,必須要了解計算機中的進程的概念。那什么是進程呢?其與線程有何關系?下面看下其概念的核心內涵:


  1.進程:每個進程都有獨立的代碼和數據空間(進程上下文),進程間的切換會有較大的開銷,一個進程包含1-n個線程。


  2.線程:同一類線程共享代碼和數據空間,每個線程有獨立的運行棧和程序計數器(PC),線程切換開銷小。


  3.關系:很顯然,進程內包含一或多個線程,且線程間共享進程所擁有的代碼和數據空間。


  同時,了解進程和線程的含義時,還需要了解如下事實:


  ·線程和進程生命周期一樣,分為五個階段:創建、就緒、運行、阻塞、終止。


  ·多進程是指操作系統能同時運行多個任務(程序),比如windows中同時運行計算器和畫圖程序等。


  ·多線程是指在同一程序中有多個任務流在執行,且每個任務流的執行非串行順序執行的。


  二、Java中創建線程的方式


  理解力線程和進程后,我們看看如何用Java語言來創建線程。


  在java中要想實現多線程,有兩種手段,一種是繼續Thread類,另外一種是實現Runable接口。


  2.1擴展java.lang.Thread類創建線程


  代碼清單-1:繼承Thread類創建的線程

image.png

  控制臺輸出的運行結果如下(注,每次運行的結果可能不一樣):

image.png

  【說明:】


  程序啟動運行的時候(運行程序),java虛擬機會立即創建主線程,主線程main在main()調用時候被創建。隨著調用main方法里的兩個對象的start方法,另外兩個線程也啟動了,這樣,整個應用就在多線程下運行。


  注意:start()方法的調用后并不是立即執行多線程代碼,而是使得該線程變為可運行態(Runnable),什么時候運行是由操作系統決定的。


  從程序運行的結果可以發現,多線程程序是亂序執行。因此,只有亂序執行的代碼才有必要設計為多線程。


  Thread.sleep()方法調用目的是不讓當前線程獨自霸占該進程所獲取的CPU資源,以留出一定時間給其他線程執行的機會。實際上所有的多線程代碼執行順序都是不確定的,每次執行的結果都是隨機的。


  另外,如果一個線程對象的start方法被重復調用,那么程序運行時會拋出異常。比如把代碼清單-1main方法中的第二個線程對象改為:


  MyThreadmTh2=mTh1;//newMyThread("Thread-B");


  其運行結果如下:

image.png

  圖-2:重復調用線程對象的start方法結果


  2.2實現java.lang.Runnable接口創建線程


  代碼清單-2:實現Runnable接口創建線程

image.png

  運行上述程序,其控制臺輸出結果(每次運行的結果不盡相同)如下:

image.png

圖-2:通過接口實現的線程運行參考結果

  【說明:】

  MyRunnableThread類通過實現Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程序的一個約定。所有的多線程代碼都在run方法里面。Thread類實際上也是實現了Runnable接口的類。


  在啟動的多線程的時候,需要先通過Thread類的構造方法Thread(Runnabletarget)構造出對象,然后調用Thread對象的start()方法來運行多線程代碼。


  實際上所有的多線程代碼都是通過運行Thread的start()方法來運行的。因此,不管是擴展Thread類還是實現Runnable接口來實現多線程,最終還是通過Thread的對象的API來控制線程的,熟悉Thread類的API是進行多線程編程的基礎。


  三、Thread和Runnable的區別


  如果一個線程類繼承Thread,則不適合線程類對象內的資源共享。但是如果實現了Runable接口的話,則很容易的實現資源共享。代碼清單如下:


  清單-3:繼承Thread線程類(和清單-1類似)


image.png

  清單-4:執行線程代碼清單

image.png

  圖-3:運行結果如下:

image.png

  從上面可以看出,不同的線程之間count是不同的(其實也是不同的線程對象),這對于賣票系統來說就會有很大的問題。當然,這里可以用同步來實現。


  接下來我們用Runnable接口來實現看看:


  清單-5:實現Runnable接口的線程

image.png

  代碼清單-6:執行實現了Runnable接口的線程類

image.png

  運行結果如下:

image.png

  圖-4:實現資源共享


  這里要注意每個線程都是用同一個實例化對象,如果不是同一個,效果就和上面的一樣了!


  【總結:】


  實現Runnable接口比繼承Thread類所具有的優勢:


  1):適合多個相同的程序代碼的線程去處理同一個資源;


  2):可以避免java中的單繼承的限制;


  3):增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立;


  另外,這里提醒說明一下:main方法其實也是一個線程。在java中所有的線程都是同時啟動的,至于什么時候,哪個先執行,完全看誰先得到CPU的資源。


  在java中,每次程序運行至少啟動2個線程。一個是main線程(前文提到過的主線程),一個是垃圾收集線程。因為每當使用java命令執行一個類的時候,實際上都會啟動一個JVM,而每一個JVM就是在操作系統中啟動了一個進程。


  四、線程狀態轉換

image.png

  1、新建狀態(New):新創建了一個線程對象。


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


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


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


  (一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。


  (二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。


  (三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。


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


  五、線程調度


  關于線程的調度的主要說明如下:


  1、調整線程優先級:Java線程有優先級,優先級高的線程會獲得較多的運行機會。


  Java線程的優先級用整數表示,取值范圍是1~10,Thread類有以下三個靜態常量:


  staticintMAX_PRIORITY線程可以具有的最高優先級,取值為10。


  staticintMIN_PRIORITY線程可以具有的最低優先級,取值為1。


  staticintNORM_PRIORITY分配給線程的默認優先級,取值為5。


  Thread類的setPriority()和getPriority()方法分別用來設置和獲取線程的優先級。


  每個線程都有默認的優先級。主線程的默認優先級為Thread.NORM_PRIORITY。


  線程的優先級有繼承關系,比如A線程中創建了B線程,那么B將和A具有相同的優先級。


  JVM提供了10個線程優先級,但與常見的操作系統都不能很好的映射。如果希望程序能移植到各個操作系統中,應該僅僅使用Thread類有以下三個靜態常量作為優先級,這樣能保證同樣的優先級采用了同樣的調度方式。


  2、線程睡眠:Thread.sleep(longmillis)方法,使線程轉到阻塞狀態。millis參數設定睡眠的時間,以毫秒為單位。當睡眠結束后,就轉為就緒(Runnable)狀態。sleep()平臺移植性好。


  3、線程等待:Object類中的wait()方法,導致當前的線程等待,直到其他線程調用此對象的notify()方法或notifyAll()喚醒方法。這個兩個喚醒方法也是Object類中的方法,行為等價于調用wait(0)一樣。


  4、線程讓步:Thread.yield()方法,暫停當前正在執行的線程對象,把執行機會讓給相同或者更高優先級的線程。


  5、線程加入:join()方法,等待其他線程終止。在當前線程中調用另一個線程的join()方法,則當前線程轉入阻塞狀態,直到另一個進程運行結束,當前線程再由阻塞轉為就緒狀態。


  6、線程喚醒:Object類中的notify()方法,喚醒在此對象監視器上等待的單個線程。如果所有線程都在此對象上等待,則會選擇喚醒其中一個線程。選擇是任意性的,并在對實現做出決定時發生。線程通過調用其中一個wait方法,在對象的監視器上等待。直到當前的線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程將以常規方式與在該對象上主動同步的其他所有線程進行競爭;例如,喚醒的線程在作為鎖定此對象的下一個線程方面沒有可靠的特權或劣勢。類似的方法還有一個notifyAll(),喚醒在此對象監視器上等待的所有線程。


  注意:


  Thread中suspend()和resume()兩個方法在JDK1.5中已經廢除,不再介紹。因為有死鎖傾向。


  以上就是動力節點java培訓機構小編介紹的“深入淺出:Java多線程編程實戰教程(實用篇)”的內容,希望對大家有幫助,更多java最新資訊請繼續關注動力節點java培訓機構官網,每天會有精彩內容分享與你。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 一区精品视频 | 亚洲激情在线看 | 二级片毛片 | 亚洲欧美精品网站在线观看 | 亚洲日本欧美日韩高观看 | 爱久久www.35669 | 欧美乱码 | 日韩视频一区 | 色老成人精品视频在线观看 | 国产成人在线免费视频 | 国产小视频精品 | 亚洲一级毛片免费在线观看 | 一级毛片免费在线播放 | 久久免费视频网 | 久久亚洲国产精品五月天 | 欧美第一页在线观看 | 鲁鲁狠色综合色综合网站 | 四虎影院精品在线观看 | 亚洲精彩视频 | 国内精品久久久久影院亚洲 | 免费乱人伦 | 中文字幕在线免费看 | 老司机深夜福利影院 | 天海翼一区二区三区高清视频 | 日韩欧美精品一区二区三区 | 久久久久美女 | 国产伦精品一区二区三区无广告 | 黄色毛片视频网站 | 日本一级毛片免费播 | 国产精品第一页爽爽影院 | 日日爽日日操 | 久久久久国产成人精品 | 91久久亚洲精品国产一区二区 | 日日摸夜夜嗷嗷叫日日拍 | 国产一区二区三区免费 | 国内精品久久久久尤物 | 欧美伊人久久久久久久久影院 | 91长腿女神清纯大又嫩在线 | 老年人一级特黄aa大片 | 国产精品成在线观看 | 亚洲精品久久久久久中文字幕小说 |