Java多線程教程之基礎(chǔ)知識(shí)講解

Java多線程教程之基礎(chǔ)知識(shí)講解

長(zhǎng)沙達(dá)內(nèi)教育      2022-03-30 14:00:02     26

Java多線程教程之基礎(chǔ)知識(shí)講解,Java多線程教程,Java支持多線程編程,因此用Java編寫(xiě)的應(yīng)用程序可以同時(shí)執(zhí)行多個(gè)任務(wù)。Java的多線程機(jī)制使用起來(lái)非常方便,用戶

課程價(jià)格 請(qǐng)咨詢

上課時(shí)段: 授課校區(qū):

詳細(xì)介紹

Java多線程教程,Java支持多線程編程,因此用Java編寫(xiě)的應(yīng)用程序可以同時(shí)執(zhí)行多個(gè)任務(wù)。Java的多線程機(jī)制使用起來(lái)非常方便,用戶只需關(guān)注程序細(xì)節(jié)的實(shí)現(xiàn),而不用擔(dān)心后臺(tái)的多任務(wù)系統(tǒng)。本文將為大家講解有關(guān)Java多線程的基礎(chǔ)知識(shí),主要內(nèi)容有多線程的概念、創(chuàng)建、優(yōu)勢(shì)和生命周期。

什么是多線程

在早期的計(jì)算機(jī)中時(shí)沒(méi)有操作系統(tǒng)的,計(jì)算機(jī)開(kāi)啟后只能執(zhí)行一個(gè)程序,直到結(jié)束。操作系統(tǒng)的出現(xiàn)使得計(jì)算機(jī)可以同時(shí)執(zhí)行多個(gè)程序,操作系統(tǒng)為每個(gè)程序分配不同的進(jìn)程,每個(gè)進(jìn)程擁有獨(dú)立的句柄、資源等,使得計(jì)算機(jī)可以同時(shí)執(zhí)行多個(gè)程序。但是進(jìn)程的創(chuàng)建和銷毀耗費(fèi)的代價(jià)太大,因此衍生出線程的概念。允許在一個(gè)進(jìn)程中創(chuàng)建多個(gè)線程,這些線程共享進(jìn)程的資源,并且每個(gè)線程擁有自己獨(dú)立的程序計(jì)數(shù)器、線程局部變量等資源。線程也被稱為進(jìn)程的輕量型運(yùn)動(dòng)實(shí)體。

創(chuàng)建多線程和啟動(dòng)

1.繼承Thread類創(chuàng)建線程類

通過(guò)繼承Thread類創(chuàng)建線程類的具體步驟和具體代碼如下:

定義一個(gè)繼承Thread類的子類,并重寫(xiě)該類的run()方法;

創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建了線程對(duì)象;

調(diào)用該線程對(duì)象的start()方法啟動(dòng)線程。

class SomeThead extends Thraad{public void run(){//do something here}}public static void main(String[]args){SomeThread oneThread=new SomeThread();

步驟3:?jiǎn)?dòng)多線程:

oneThread.start();}

2.實(shí)現(xiàn)Runnable接口創(chuàng)建線程類

通過(guò)實(shí)現(xiàn)Runnable接口創(chuàng)建線程類的具體步驟和具體代碼如下:

定義Runnable接口的實(shí)現(xiàn)類,并重寫(xiě)該接口的run()方法;

創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此實(shí)例作為T(mén)hread的target對(duì)象,即該Thread對(duì)象才是真正的線程對(duì)象。

class SomeRunnable implements Runnable{public void run(){//do something here}}Runnable oneRunnable=new SomeRunnable();Thread oneThread=new Thread(oneRunnable);oneThread.start();

3.通過(guò)Callable和Future創(chuàng)建線程

通過(guò)Callable和Future創(chuàng)建線程的具體步驟和具體代碼如下:

創(chuàng)建Callable接口的實(shí)現(xiàn)類,并實(shí)現(xiàn)call()方法,該call()方法將作為線程執(zhí)行體,并且有返回值。

創(chuàng)建Callable實(shí)現(xiàn)類的實(shí)例,使用FutureTask類來(lái)包裝Callable對(duì)象,該FutureTask對(duì)象封裝了該Callable對(duì)象的call()方法的返回值。

使用FutureTask對(duì)象作為T(mén)hread對(duì)象的target創(chuàng)建并啟動(dòng)新線程。

調(diào)用FutureTask對(duì)象的get()方法來(lái)獲得子線程執(zhí)行結(jié)束后的返回值其中,Callable接口(也只有一個(gè)方法)定義如下:

public interface Callable{V call()throws Exception;}

步驟1:創(chuàng)建實(shí)現(xiàn)Callable接口的類SomeCallable(略);

步驟2:創(chuàng)建一個(gè)類對(duì)象:

Callable oneCallable=new SomeCallable();

步驟3:由Callable創(chuàng)建一個(gè)FutureTask對(duì)象:

FutureTask oneTask=new FutureTask(oneCallable);

注釋:FutureTask是一個(gè)包裝器,它通過(guò)接受Callable來(lái)創(chuàng)建,它同時(shí)實(shí)現(xiàn)了Future和Runnable接口。

步驟4:由FutureTask創(chuàng)建一個(gè)Thread對(duì)象:

Thread oneThread=new Thread(oneTask);

步驟5:?jiǎn)?dòng)線程:

oneThread.start();

多線程的優(yōu)勢(shì)

多線程的出現(xiàn)帶來(lái)很多的好處:

  • 發(fā)揮多核處理器的性能:在多喝處理器上執(zhí)行單線程任務(wù)是對(duì)多核的浪費(fèi),因?yàn)榭傆泻诵脑诳臻e著,多線程的出現(xiàn)能充分發(fā)揮多核的優(yōu)勢(shì)。
  • 化整為零:往往在一個(gè)復(fù)雜的應(yīng)用中包含許多不同類型的任務(wù),將這些不同類型的任務(wù)分配給不同的線程去執(zhí)行會(huì)比將其混在同一個(gè)線程中去執(zhí)行要好,因?yàn)槊總€(gè)線程更加的簡(jiǎn)單清晰,更容易測(cè)試等。
  • 異步事件處理:當(dāng)一個(gè)線程處理的任務(wù)遇到阻塞時(shí)如IO阻塞,cpu可以調(diào)度其他線程去執(zhí)行而不是在那傻傻的等到IO結(jié)束在執(zhí)行其他任務(wù)。
  • 更好的用戶體驗(yàn):當(dāng)多個(gè)用戶像你的服務(wù)發(fā)送請(qǐng)求時(shí),你一個(gè)線程依次執(zhí)行任務(wù)會(huì)使得排在后面的用戶等待時(shí)間過(guò)長(zhǎng)得不到響應(yīng),帶來(lái)不好的體驗(yàn)。但使用多個(gè)線程可以讓每個(gè)用戶都能很快的得到響應(yīng)(盡管這不能高執(zhí)行速度),用戶會(huì)覺(jué)得自己的請(qǐng)求正在被處理,獲得更好的體驗(yàn)。

多線程的生命周期

1.新建狀態(tài)

用new關(guān)鍵字和Thread類或其子類建立一個(gè)線程對(duì)象后,該線程對(duì)象就處于新生狀態(tài)。處于新生狀態(tài)的線程有自己的內(nèi)存空間,通過(guò)調(diào)用start方法進(jìn)入就緒狀態(tài)(runnable)。

注意:不能對(duì)已經(jīng)啟動(dòng)的線程再次調(diào)用start()方法,否則會(huì)出現(xiàn)Java.lang.IllegalThreadStateException異常。

2.就緒狀態(tài)

處于就緒狀態(tài)的線程已經(jīng)具備了運(yùn)行條件,但還沒(méi)有分配到CPU,處于線程就緒隊(duì)列(盡管是采用隊(duì)列形式,事實(shí)上,把它稱為可運(yùn)行池而不是可運(yùn)行隊(duì)列。因?yàn)閏pu的調(diào)度不一定是按照先進(jìn)先出的順序來(lái)調(diào)度的),等待系統(tǒng)為其分配CPU。等待狀態(tài)并不是執(zhí)行狀態(tài),當(dāng)系統(tǒng)選定一個(gè)等待執(zhí)行的Thread對(duì)象后,它就會(huì)從等待執(zhí)行狀態(tài)進(jìn)入執(zhí)行狀態(tài),系統(tǒng)挑選的動(dòng)作稱之為“cpu調(diào)度”。一旦獲得CPU,線程就進(jìn)入運(yùn)行狀態(tài)并自動(dòng)調(diào)用自己的run方法。

提示:如果希望子線程調(diào)用start()方法后立即執(zhí)行,可以使用Thread.sleep()方式使主線程睡眠一伙兒,轉(zhuǎn)去執(zhí)行子線程。

3.運(yùn)行狀態(tài)

處于運(yùn)行狀態(tài)的線程最為復(fù)雜,它可以變?yōu)樽枞麪顟B(tài)、就緒狀態(tài)和死亡狀態(tài)。

處于就緒狀態(tài)的線程,如果獲得了cpu的調(diào)度,就會(huì)從就緒狀態(tài)變?yōu)檫\(yùn)行狀態(tài),執(zhí)行run()方法中的任務(wù)。如果該線程失去了cpu資源,就會(huì)又從運(yùn)行狀態(tài)變?yōu)榫途w狀態(tài)。重新等待系統(tǒng)分配資源。也可以對(duì)在運(yùn)行狀態(tài)的線程調(diào)用yield()方法,它就會(huì)讓出cpu資源,再次變?yōu)榫途w狀態(tài)。

注:當(dāng)發(fā)生如下情況是,線程會(huì)從運(yùn)行狀態(tài)變?yōu)樽枞麪顟B(tài):

①線程調(diào)用sleep方法主動(dòng)放棄所占用的系統(tǒng)資源

②線程調(diào)用一個(gè)阻塞式IO方法,在該方法返回之前,該線程被阻塞

③線程試圖獲得一個(gè)同步監(jiān)視器,但更改同步監(jiān)視器正被其他線程所持有

④線程在等待某個(gè)通知(notify)

⑤程序調(diào)用了線程的suspend方法將線程掛起。不過(guò)該方法容易導(dǎo)致死鎖,所以程序應(yīng)該盡量避免使用該方法。

當(dāng)線程的run()方法執(zhí)行完,或者被強(qiáng)制性地終止,例如出現(xiàn)異常,或者調(diào)用了stop()、desyory()方法等等,就會(huì)從運(yùn)行狀態(tài)轉(zhuǎn)變?yōu)樗劳鰻顟B(tài)。

4.阻塞狀態(tài)

處于運(yùn)行狀態(tài)的線程在某些情況下,如執(zhí)行了sleep(睡眠)方法,或等待I/O設(shè)備等資源,將讓出CPU并暫時(shí)停止自己的運(yùn)行,進(jìn)入阻塞狀態(tài)。在阻塞狀態(tài)的線程不能進(jìn)入就緒隊(duì)列。只有當(dāng)引起阻塞的原因消除時(shí),如睡眠時(shí)間已到,或等待的I/O設(shè)備空閑下來(lái),線程便轉(zhuǎn)入就緒狀態(tài),重新到就緒隊(duì)列中排隊(duì)等待,被系統(tǒng)選中后從原來(lái)停止的位置開(kāi)始繼續(xù)運(yùn)行。有三種方法可以暫停Threads執(zhí)行:

5.死亡狀態(tài)

當(dāng)線程的run()方法執(zhí)行完,或者被強(qiáng)制性地終止,就認(rèn)為它死去。這個(gè)線程對(duì)象也許是活的,但是,它已經(jīng)不是一個(gè)單獨(dú)執(zhí)行的線程。線程一旦死亡,就不能復(fù)生。如果在一個(gè)死去的線程上調(diào)用start()方法,會(huì)拋出java.lang.IllegalThreadStateException異常。

以上就是長(zhǎng)沙達(dá)內(nèi)教育java培訓(xùn)機(jī)構(gòu)的小編針對(duì)“Java多線程教程之基礎(chǔ)知識(shí)講解”的內(nèi)容進(jìn)行的回答,希望對(duì)大家有所幫助,如有疑問(wèn),請(qǐng)?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為你服務(wù)。

Java教程

培訓(xùn)啦提醒您:交易時(shí)請(qǐng)核實(shí)對(duì)方資質(zhì),對(duì)于過(guò)大宣傳或承諾需謹(jǐn)慎!任何要求預(yù)付定金、匯款等方式均存在風(fēng)險(xiǎn),謹(jǐn)防上當(dāng)。