黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

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

深入淺出:Java多線程編程實(shí)戰(zhàn)教程(實(shí)用篇)

更新時(shí)間:2019-09-26 10:08:58 來源:動(dòng)力節(jié)點(diǎn) 瀏覽4135次



image.png

  一、進(jìn)程和線程概念


  在開始java線程的學(xué)習(xí)前,必須要了解計(jì)算機(jī)中的進(jìn)程的概念。那什么是進(jìn)程呢?其與線程有何關(guān)系?下面看下其概念的核心內(nèi)涵:


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


  2.線程:同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程切換開銷小。


  3.關(guān)系:很顯然,進(jìn)程內(nèi)包含一或多個(gè)線程,且線程間共享進(jìn)程所擁有的代碼和數(shù)據(jù)空間。


  同時(shí),了解進(jìn)程和線程的含義時(shí),還需要了解如下事實(shí):


  ·線程和進(jìn)程生命周期一樣,分為五個(gè)階段:創(chuàng)建、就緒、運(yùn)行、阻塞、終止。


  ·多進(jìn)程是指操作系統(tǒng)能同時(shí)運(yùn)行多個(gè)任務(wù)(程序),比如windows中同時(shí)運(yùn)行計(jì)算器和畫圖程序等。


  ·多線程是指在同一程序中有多個(gè)任務(wù)流在執(zhí)行,且每個(gè)任務(wù)流的執(zhí)行非串行順序執(zhí)行的。


  二、Java中創(chuàng)建線程的方式


  理解力線程和進(jìn)程后,我們看看如何用Java語言來創(chuàng)建線程。


  在java中要想實(shí)現(xiàn)多線程,有兩種手段,一種是繼續(xù)Thread類,另外一種是實(shí)現(xiàn)Runable接口。


  2.1擴(kuò)展java.lang.Thread類創(chuàng)建線程


  代碼清單-1:繼承Thread類創(chuàng)建的線程

image.png

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

image.png

  【說明:】


  程序啟動(dòng)運(yùn)行的時(shí)候(運(yùn)行程序),java虛擬機(jī)會(huì)立即創(chuàng)建主線程,主線程main在main()調(diào)用時(shí)候被創(chuàng)建。隨著調(diào)用main方法里的兩個(gè)對象的start方法,另外兩個(gè)線程也啟動(dòng)了,這樣,整個(gè)應(yīng)用就在多線程下運(yùn)行。


  注意:start()方法的調(diào)用后并不是立即執(zhí)行多線程代碼,而是使得該線程變?yōu)榭蛇\(yùn)行態(tài)(Runnable),什么時(shí)候運(yùn)行是由操作系統(tǒng)決定的。


  從程序運(yùn)行的結(jié)果可以發(fā)現(xiàn),多線程程序是亂序執(zhí)行。因此,只有亂序執(zhí)行的代碼才有必要設(shè)計(jì)為多線程。


  Thread.sleep()方法調(diào)用目的是不讓當(dāng)前線程獨(dú)自霸占該進(jìn)程所獲取的CPU資源,以留出一定時(shí)間給其他線程執(zhí)行的機(jī)會(huì)。實(shí)際上所有的多線程代碼執(zhí)行順序都是不確定的,每次執(zhí)行的結(jié)果都是隨機(jī)的。


  另外,如果一個(gè)線程對象的start方法被重復(fù)調(diào)用,那么程序運(yùn)行時(shí)會(huì)拋出異常。比如把代碼清單-1main方法中的第二個(gè)線程對象改為:


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


  其運(yùn)行結(jié)果如下:

image.png

  圖-2:重復(fù)調(diào)用線程對象的start方法結(jié)果


  2.2實(shí)現(xiàn)java.lang.Runnable接口創(chuàng)建線程


  代碼清單-2:實(shí)現(xiàn)Runnable接口創(chuàng)建線程

image.png

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

image.png

圖-2:通過接口實(shí)現(xiàn)的線程運(yùn)行參考結(jié)果

  【說明:】

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


  在啟動(dòng)的多線程的時(shí)候,需要先通過Thread類的構(gòu)造方法Thread(Runnabletarget)構(gòu)造出對象,然后調(diào)用Thread對象的start()方法來運(yùn)行多線程代碼。


  實(shí)際上所有的多線程代碼都是通過運(yùn)行Thread的start()方法來運(yùn)行的。因此,不管是擴(kuò)展Thread類還是實(shí)現(xiàn)Runnable接口來實(shí)現(xiàn)多線程,最終還是通過Thread的對象的API來控制線程的,熟悉Thread類的API是進(jìn)行多線程編程的基礎(chǔ)。


  三、Thread和Runnable的區(qū)別


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


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


image.png

  清單-4:執(zhí)行線程代碼清單

image.png

  圖-3:運(yùn)行結(jié)果如下:

image.png

  從上面可以看出,不同的線程之間count是不同的(其實(shí)也是不同的線程對象),這對于賣票系統(tǒng)來說就會(huì)有很大的問題。當(dāng)然,這里可以用同步來實(shí)現(xiàn)。


  接下來我們用Runnable接口來實(shí)現(xiàn)看看:


  清單-5:實(shí)現(xiàn)Runnable接口的線程

image.png

  代碼清單-6:執(zhí)行實(shí)現(xiàn)了Runnable接口的線程類

image.png

  運(yùn)行結(jié)果如下:

image.png

  圖-4:實(shí)現(xiàn)資源共享


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


  【總結(jié):】


  實(shí)現(xiàn)Runnable接口比繼承Thread類所具有的優(yōu)勢:


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


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


  3):增加程序的健壯性,代碼可以被多個(gè)線程共享,代碼和數(shù)據(jù)獨(dú)立;


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


  在java中,每次程序運(yùn)行至少啟動(dòng)2個(gè)線程。一個(gè)是main線程(前文提到過的主線程),一個(gè)是垃圾收集線程。因?yàn)槊慨?dāng)使用java命令執(zhí)行一個(gè)類的時(shí)候,實(shí)際上都會(huì)啟動(dòng)一個(gè)JVM,而每一個(gè)JVM就是在操作系統(tǒng)中啟動(dòng)了一個(gè)進(jìn)程。


  四、線程狀態(tài)轉(zhuǎn)換

image.png

  1、新建狀態(tài)(New):新創(chuàng)建了一個(gè)線程對象。


  2、就緒狀態(tài)(Runnable):線程對象創(chuàng)建后,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,變得可運(yùn)行,等待獲取CPU的使用權(quán)。


  3、運(yùn)行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。


  4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán),暫時(shí)停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞的情況分三種:


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


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


  (三)、其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)。


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


  五、線程調(diào)度


  關(guān)于線程的調(diào)度的主要說明如下:


  1、調(diào)整線程優(yōu)先級:Java線程有優(yōu)先級,優(yōu)先級高的線程會(huì)獲得較多的運(yùn)行機(jī)會(huì)。


  Java線程的優(yōu)先級用整數(shù)表示,取值范圍是1~10,Thread類有以下三個(gè)靜態(tài)常量:


  staticintMAX_PRIORITY線程可以具有的最高優(yōu)先級,取值為10。


  staticintMIN_PRIORITY線程可以具有的最低優(yōu)先級,取值為1。


  staticintNORM_PRIORITY分配給線程的默認(rèn)優(yōu)先級,取值為5。


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


  每個(gè)線程都有默認(rèn)的優(yōu)先級。主線程的默認(rèn)優(yōu)先級為Thread.NORM_PRIORITY。


  線程的優(yōu)先級有繼承關(guān)系,比如A線程中創(chuàng)建了B線程,那么B將和A具有相同的優(yōu)先級。


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


  2、線程睡眠:Thread.sleep(longmillis)方法,使線程轉(zhuǎn)到阻塞狀態(tài)。millis參數(shù)設(shè)定睡眠的時(shí)間,以毫秒為單位。當(dāng)睡眠結(jié)束后,就轉(zhuǎn)為就緒(Runnable)狀態(tài)。sleep()平臺移植性好。


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


  4、線程讓步:Thread.yield()方法,暫停當(dāng)前正在執(zhí)行的線程對象,把執(zhí)行機(jī)會(huì)讓給相同或者更高優(yōu)先級的線程。


  5、線程加入:join()方法,等待其他線程終止。在當(dāng)前線程中調(diào)用另一個(gè)線程的join()方法,則當(dāng)前線程轉(zhuǎn)入阻塞狀態(tài),直到另一個(gè)進(jìn)程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒狀態(tài)。


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


  注意:


  Thread中suspend()和resume()兩個(gè)方法在JDK1.5中已經(jīng)廢除,不再介紹。因?yàn)橛兴梨i傾向。


  以上就是動(dòng)力節(jié)點(diǎn)java培訓(xùn)機(jī)構(gòu)小編介紹的“深入淺出:Java多線程編程實(shí)戰(zhàn)教程(實(shí)用篇)”的內(nèi)容,希望對大家有幫助,更多java最新資訊請繼續(xù)關(guān)注動(dòng)力節(jié)點(diǎn)java培訓(xùn)機(jī)構(gòu)官網(wǎng),每天會(huì)有精彩內(nèi)容分享與你。

提交申請后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: a级aaaaaaaa毛片| 欧美色p| 午夜看一级特黄a大片黑 | 麻豆果冻传媒新剧国产短视频 | 天天舔天天色 | 日韩免费一级毛片 | 伊人激情综合 | 中文字幕一区二区三区在线观看 | 夜夜爽夜夜叫夜夜高潮漏水 | 国产精品亚洲高清一区二区 | 日本高清三区 | 中国毛片在线观看 | 日韩高清一区二区三区不卡 | 香焦视频在线观看黄 | 欧美成人综合视频 | 日日摸夜夜欧美一区二区 | 欧美成人禁片在线www | 欧美日韩久久中文字幕 | 国产 字幕 制服 中文 在线 | 亚洲国产欧美日韩一区二区 | 国产成人精品视频免费 | 午夜爱爱毛片xxxx视频免费看 | 2020国产成人精品视频人 | 亚洲欧美v国产一区二区 | 日皮视频免费 | 中文字幕日本一区久久 | 国产情侣草莓视频在线 | 午夜剧场免费体验 | 国产黄网永久免费 | 黄色免费毛片 | 2021精品国夜夜天天拍拍 | 亚洲免费国产 | 521a久久九九久久精品 | 日日摸夜夜添免费毛片小说 | 亚洲中文字幕特级毛片 | 天堂色视频| 国产精品青草久久福利不卡 | 在线观看免费视频一区 | 91精品成人免费国产 | 中文字幕第9页 | 在线观看 日韩 |