国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > Java > 正文

Java基礎(chǔ)之多線(xiàn)程

2024-07-14 08:42:21
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

線(xiàn)程中run()和start()的區(qū)別:
對(duì)于Thread對(duì)象來(lái)說(shuō),當(dāng)你調(diào)用的是start(),線(xiàn)程會(huì)被放到等待隊(duì)列,等待CPU調(diào)度,不一定馬上執(zhí)行;無(wú)需等待run()方法執(zhí)行完畢,可以直接執(zhí)行下面的代碼;
而調(diào)用的是run()的話(huà),就是當(dāng)做普通的方法調(diào)用,程序還是要順序執(zhí)行的;
新建線(xiàn)程的幾種方式:
實(shí)現(xiàn)Runnable接口;里面實(shí)現(xiàn)run()方法;
然后把這個(gè)實(shí)現(xiàn)了Runnable接口的類(lèi)就新建為一個(gè)Thread t = new Thread(new (實(shí)現(xiàn)Runnable接口的類(lèi))),調(diào)用start()方法即可開(kāi)始一個(gè)線(xiàn)程了。記住,start()只是開(kāi)啟,然后就會(huì)返回,繼續(xù)執(zhí)行start()下面的語(yǔ)句了。

線(xiàn)程執(zhí)行器:
我們可以通過(guò)不同的線(xiàn)程執(zhí)行器來(lái)實(shí)現(xiàn)多線(xiàn)程的執(zhí)行,有以下幾種執(zhí)行器:

ExecutorService exec = Executors.newCachedThreadPool();

ExecutorService exec = Executors.newFixedThreadPool(5);

ExecutorService exec = Executors.newSingleThreadExecutor();

我們可以對(duì)比一下這三者的區(qū)別:第一個(gè)執(zhí)行會(huì)為每一個(gè)任務(wù)都創(chuàng)建一個(gè)線(xiàn)程,
而第二個(gè)則是可以一次性指定要分配多少線(xiàn)程,而第三個(gè)則是屬于單線(xiàn)程,會(huì)一個(gè)線(xiàn)程一個(gè)線(xiàn)程的依次執(zhí)行;

休眠:
會(huì)使得任務(wù)中斷一段時(shí)間,相當(dāng)于變相的阻塞了,可以給其他線(xiàn)程制造機(jī)會(huì)去執(zhí)行;
但是我們不能通過(guò)sleep()來(lái)試圖控制線(xiàn)程的順序執(zhí)行,而是要考慮用同步控制來(lái)實(shí)現(xiàn);

讓步:
通過(guò)使用yield()方法來(lái)給線(xiàn)程調(diào)度機(jī)制一個(gè)暗示:你的工作已經(jīng)完成的差不多了,可以讓別的線(xiàn)程使用CPU了,其功能上跟sleep()其實(shí)是差不多的。

后臺(tái)線(xiàn)程:
指在程序運(yùn)行的時(shí)候在后臺(tái)提供一種通用服務(wù)的線(xiàn)程,并且這種線(xiàn)程并不屬于程序總共不可或缺的部分,當(dāng)所有非后臺(tái)線(xiàn)程結(jié)束時(shí),程序終止;由后臺(tái)線(xiàn)程創(chuàng)建的線(xiàn)程也是后臺(tái)線(xiàn)程;
在線(xiàn)程調(diào)用start()之前,調(diào)用setDaemon(true);

實(shí)現(xiàn)多線(xiàn)程的另一種方式:
通過(guò)繼承Thread的方式來(lái)實(shí)現(xiàn):而且run()方法是放在構(gòu)造函數(shù)里面的,也就是說(shuō),當(dāng)初始化一個(gè)線(xiàn)程的時(shí)候,就自動(dòng)的開(kāi)啟了線(xiàn)程,記得run()方法里面一般都是一個(gè)while()循環(huán);

加入一個(gè)線(xiàn)程:
一個(gè)線(xiàn)程可以在其他線(xiàn)程之上調(diào)用join()方法,如果某個(gè)線(xiàn)程在另一個(gè)線(xiàn)程t上調(diào)用t.join();此線(xiàn)程將被掛起,知道目標(biāo)線(xiàn)程t結(jié)束才恢復(fù);
join()方法,你在一個(gè)線(xiàn)程中join()了一個(gè)線(xiàn)程進(jìn)來(lái),你就要等待這個(gè)線(xiàn)程結(jié)束了,才可以把自己這個(gè)線(xiàn)程給結(jié)束掉;join()的底層實(shí)現(xiàn)是wait()方法;

同步:
Synchronzied;可以用在方法上,也可以用到類(lèi)上面;

顯式地使用lock對(duì)象
先用Lock lock = new ReentrantLock();建出一個(gè)鎖對(duì)象出來(lái),然后在方法里面,先調(diào)用lock.lock();然后try語(yǔ)句里面是方法體,最后記得要在finally里面加上lock.unlock();這樣就就相當(dāng)于解鎖了。

區(qū)別:
可以看到synchronized lock相比起來(lái),lock似乎要加上一些try/catch語(yǔ)句才可以,但是,這也是好處之一,比起synchronized,可以多出來(lái)處理的過(guò)程,讓用戶(hù)出現(xiàn)錯(cuò)誤的可能性降低;
使用原子類(lèi)也可以實(shí)現(xiàn)資源共享的問(wèn)題,但是原子類(lèi)一般很少在常規(guī)編程中用到,用于性能調(diào)優(yōu),然后AtomicInteger,AtomicLong等原子類(lèi),使用這些的時(shí)候,不需要用到synchronized和lock,但是原子類(lèi)很少用到,所以我們還是用synchronized和lock。

線(xiàn)程的狀態(tài):
新建;就緒;阻塞;死亡;

導(dǎo)致阻塞的幾個(gè)原因:
1,通過(guò)調(diào)用sleep()使任務(wù)進(jìn)入休眠狀態(tài),

2,通過(guò)調(diào)用wait()使線(xiàn)程掛起,知道線(xiàn)程得到notify()notifyAll()消息,

3,任務(wù)再等待某個(gè)輸入/輸出完成;

4,任務(wù)視圖在某個(gè)對(duì)象上調(diào)用其同步控制方法,但是對(duì)象鎖不可用,因?yàn)榱硪粋€(gè)任務(wù)已經(jīng)獲取了這個(gè)鎖;

中斷:
這是一個(gè)大學(xué)問(wèn)呀。一般的話(huà),我們中斷都是用interrupted(),但是,我們現(xiàn)在說(shuō)了,用Executor執(zhí)行器可以更好地執(zhí)行了,所以我們?nèi)缛绾卧趫?zhí)行器中中斷線(xiàn)程呢?這也很好辦,用Executor的shutdownNow(),但是,這又是一個(gè)問(wèn)題了,這只是用來(lái)中斷所有的線(xiàn)程的,但是我們是想要中斷某一個(gè)線(xiàn)層那該怎么辦呢?這就用到了返回式了,通過(guò)submit()來(lái)啟動(dòng)任務(wù)的時(shí)候,我們就能夠得到返回的類(lèi)型Future<?>通過(guò)這個(gè)去調(diào)用calcel()來(lái)中斷某個(gè)線(xiàn)程。具體等一下碼,現(xiàn)在還要討論的還有一個(gè)問(wèn)題,中斷的線(xiàn)程是否有一些是無(wú)法中斷的,判定如下:如果是在sleep()中的線(xiàn)程,那么顯然是可以中斷的,但是對(duì)于正在讀取I/O的線(xiàn)程和正在試圖獲取鎖的線(xiàn)程,我們是無(wú)法中斷的,而中斷線(xiàn)程就相當(dāng)于拋出了一個(gè)異常,方便我們關(guān)閉掉資源。

線(xiàn)程之間的協(xié)作:
當(dāng)線(xiàn)程同時(shí)運(yùn)行多個(gè)任務(wù)時(shí),我們可以用鎖來(lái)同步兩個(gè)任務(wù)的行為,同時(shí)也可以用wait()notifyAll()來(lái)實(shí)現(xiàn)對(duì)線(xiàn)程的控制;
wait()就是一種掛起的狀態(tài),當(dāng)你掛起了之后,鎖將被釋放,把空出來(lái)的線(xiàn)程,給別人執(zhí)行,而等到被調(diào)用notify()喚醒之后,又會(huì)重新獲得之前wait()鎖,如果這個(gè)時(shí)候鎖正在被使用的話(huà),就要陷入等待了。

wait()跟sleep()之間的區(qū)別:
1,在synchronized中,wait()期間對(duì)象鎖是釋放的;而sleep()鎖是不會(huì)釋放的;

2,可以通過(guò)notify(),notifyAll(),或者令時(shí)間到期,從wait()中恢復(fù)執(zhí)行;

喚醒的區(qū)別:
notify()方法保證的喚醒是指喚醒的是恰當(dāng)?shù)娜蝿?wù),另外,為了使用notify(),你必須等待相同的條件,而對(duì)于notifyAll()來(lái)說(shuō),是否所有的線(xiàn)程都會(huì)被喚醒呢?只有當(dāng)notifyAll()因某個(gè)特定鎖被調(diào)用時(shí),只有等待這個(gè)鎖的任務(wù)才能被喚醒;

除了wait()和notify(),我們還可以顯式地使用lock和Condition對(duì)象;
使用互斥并允許任務(wù)掛起的基本類(lèi)是Condition;可以通過(guò)在Condition上調(diào)用await來(lái)掛起一個(gè)任務(wù),通過(guò)signal()來(lái)通知這個(gè)任務(wù),喚醒這個(gè)任務(wù),或者調(diào)用signalAll()來(lái)喚醒所有在這個(gè)Condition上被其自身掛起的任務(wù);與使用notify()相比,signlAll()是更安全的方式;

 

Lock lock = new ReentrantLock();Condition condition = lock.newCondition();lock.lock();lock.unlock();condition.await();

 

但是我們要知道顯式的lock對(duì)象,相比起wait(),notify()來(lái)說(shuō),更加復(fù)雜,所以還是建議用回原來(lái)的那個(gè)wait(),LockCondition只有在更加困難的多線(xiàn)程問(wèn)題才是必需的;

死鎖:
當(dāng)某一個(gè)任務(wù)在等待另一個(gè)任務(wù)的鎖釋放,而下一個(gè)任務(wù)又在等待上一個(gè)鎖的釋放,在這樣呈鏈?zhǔn)降难h(huán)里面,直到這個(gè)鏈條上的任務(wù)又在等待第一個(gè)任務(wù)釋放鎖,得到了一個(gè)任務(wù)之間的相互等待的連續(xù)循環(huán);稱(chēng)為死鎖;
哲學(xué)家就餐問(wèn)題;經(jīng)典的死鎖問(wèn)題;
發(fā)生死鎖的四個(gè)滿(mǎn)足條件:

1,互斥條件,任務(wù)使用的資源中國(guó)至少有一個(gè)是不能共享的。

2,至少有一個(gè)任務(wù)它必須持有一個(gè)資源把那個(gè)正在等待獲取另一個(gè)被別的任務(wù)持有的資源;

3,資源不能被任務(wù)搶占;

4,必須要有等待循環(huán);

防止死鎖的最容易的方式是破壞第四個(gè)條件。

總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)VeVb武林網(wǎng)的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JAVA教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 永寿县| 安吉县| 昌邑市| 武宣县| 栖霞市| 西林县| 获嘉县| 肃南| 治县。| 肃北| 广丰县| 九寨沟县| 巴青县| 开原市| 肥东县| 永新县| 海阳市| 新巴尔虎左旗| 柯坪县| 靖远县| 聊城市| 济源市| 利辛县| 军事| 雅安市| 富阳市| 阜平县| 合川市| 曲沃县| 临高县| 健康| 舞钢市| 建水县| 青冈县| 静宁县| 隆昌县| 巴南区| 新巴尔虎左旗| 葫芦岛市| 桃园县| 梓潼县|