Java多線程筆記

1碉纺、多線程基本概念

  • 程序(program)是為了完成特定任務(wù),用某種語言編寫的一組指令的集合
  • 進(jìn)程(process)是程序執(zhí)行的一次過程刻撒,或是正在運(yùn)行的程序骨田,是一個(gè)動(dòng)態(tài)的過程,有自己的生命周期
  • 線程(thread)是程序內(nèi)部執(zhí)行的一條路徑声怔,每個(gè)線程擁有獨(dú)立的運(yùn)行棧态贤、計(jì)數(shù)器
  • 多個(gè)線程共享一個(gè)進(jìn)程內(nèi)的內(nèi)存地址、堆數(shù)據(jù)

2醋火、并行與并發(fā)的區(qū)別

  • 并行:多個(gè)cpu同時(shí)執(zhí)行多個(gè)任務(wù)悠汽,發(fā)生在某一刻
  • 并發(fā):一個(gè)cpu同時(shí)執(zhí)行多個(gè)任務(wù),發(fā)生在某個(gè)時(shí)間段芥驳,如: 秒殺活動(dòng)

3柿冲、創(chuàng)建線程的方式

3.1 方式一:繼承Thread類

1、繼承Thread類兆旬,重寫父類的run()方法
2假抄、調(diào)用線程對象的start()方法,而不是run()方法

3.2 方式二:實(shí)現(xiàn)Runnable接口

1、實(shí)現(xiàn)Runnable接口慨亲,重寫接口的run()方法
2婚瓜、通過Thread類的構(gòu)造器創(chuàng)建多線程
3、將Runnable的實(shí)現(xiàn)類作為參數(shù)傳遞給Thread類的構(gòu)造器刑棵,創(chuàng)建Thread類的對象
4巴刻、調(diào)用Thread類的start()方法開啟線程

3.3 方式三:實(shí)現(xiàn)Callable接口

1、實(shí)現(xiàn)Callable接口蛉签,重寫call()方法
2胡陪、將Callable接口的實(shí)現(xiàn)類作為參數(shù),傳遞給FutureTask類的構(gòu)造器碍舍,創(chuàng)建FutureTask類的對象
3柠座、將FutureTask類作為參數(shù)傳遞給Thread類的構(gòu)造器,創(chuàng)建Thread類的對象
4片橡、調(diào)用Thread類的start()方法開啟線程
5妈经、較Runnable相比,具有返回值捧书、可拋出異常
6吹泡、獲取返回值,需借助FutureTask類的get()方法经瓷,在開啟start()方法之后調(diào)用

3.4 方式四:創(chuàng)建線程池

背景:經(jīng)常創(chuàng)建和銷毀爆哑,使用量特別大的資源,比如并發(fā)編程對性能影響很大
解決思路:提前創(chuàng)建好多個(gè)線程舆吮,放入線程池揭朝,使用時(shí)直接獲取,使用放回池中色冀,避免了頻繁創(chuàng)建和銷毀線程的開銷


image.png

注意事項(xiàng):
1潭袱、如果調(diào)用的run()方法,那就跟調(diào)用普通方法一樣呐伞,無法啟動(dòng)多線程
2敌卓、一個(gè)線程只能調(diào)用一次start()方法,多次調(diào)用將拋出異常 "IIIeglThreadStateException"

4伶氢、繼承方式和實(shí)現(xiàn)方式的區(qū)別

  • 繼承Thread:線程代碼存放在Thread子類run()方法中
  • 實(shí)現(xiàn)Runnable:線程代碼存放在接口的子類的run()方法中
  • 實(shí)現(xiàn)Runnable方式,避免了單繼承的局限性
  • 多個(gè)線程可以共享同一個(gè)接口實(shí)現(xiàn)類的對象(也叫共享數(shù)據(jù))瘪吏,適合多個(gè)線程來處理同一份資源

5癣防、多線程引發(fā)出來的連鎖思考

  • 由于單線程不能很好的利用cpu資源,因此使用多線程來同時(shí)處理程序掌眠,加快響應(yīng)速度
  • 使用多線程蕾盯,肯定會(huì)涉及到多個(gè)線程共同搶占一個(gè)資源的問題,會(huì)帶來線程不安全
  • 解決線程不安全蓝丙,就要使用同步方式级遭,鎖定共享數(shù)據(jù)
  • 即一次只能被一個(gè)線程使用望拖,使用完之后,釋放鎖讓下一個(gè)線程使用

6挫鸽、Thread常用方法

1说敏、start():啟動(dòng)當(dāng)前線程;調(diào)用當(dāng)前線程的run()
2丢郊、run(): 通常需要重寫Thread類中的此方法盔沫,將創(chuàng)建的線程要執(zhí)行的操作聲明在此方法中
3、currentThread():靜態(tài)方法枫匾,返回執(zhí)行當(dāng)前代碼的線程
4架诞、getName():獲取當(dāng)前線程的名字
5、setName():設(shè)置當(dāng)前線程的名字
6干茉、yield():釋放當(dāng)前cpu的執(zhí)行權(quán)
7谴忧、join():在線程a中調(diào)用線程b的join(),此時(shí)線程a就進(jìn)入阻塞狀態(tài),直到線程b完全執(zhí)行完以后角虫,線程a才結(jié)束阻塞狀態(tài)沾谓。
8、stop():已過時(shí)上遥。當(dāng)執(zhí)行此方法時(shí)搏屑,強(qiáng)制結(jié)束當(dāng)前線程。
9粉楚、sleep(long millitime):讓當(dāng)前線程“睡眠”指定的millitime毫秒辣恋。在指定的millitime毫秒時(shí)間內(nèi),當(dāng)前線程是阻塞狀態(tài)模软。
10伟骨、isAlive():判斷當(dāng)前線程是否存活

7、 線程優(yōu)先級

  • MAX_PRIORITY:10
  • MIN _PRIORITY:1
  • NORM_PRIORITY:5 -->默認(rèn)優(yōu)先級
  • getPriority():獲取線程的優(yōu)先級
  • setPriority(int p):設(shè)置線程的優(yōu)先級

高優(yōu)先級的線程要搶占低優(yōu)先級線程cpu的執(zhí)行權(quán)燃异。但是只是從概率上講携狭,高優(yōu)先級的線程高概率的情況下
被執(zhí)行。并不意味著只有當(dāng)高優(yōu)先級的線程執(zhí)行完以后回俐,低優(yōu)先級的線程才執(zhí)行逛腿。

7、線程的生命周期

1仅颇、新建:當(dāng)一個(gè)Thread類或其子類的對象被實(shí)例化单默,新生的線程處理新建狀態(tài)
2、就緒:當(dāng)新建的線程被start()后忘瓦,線程處理就緒搁廓,等待著cpu時(shí)間片,具備運(yùn)行條件
3、運(yùn)行:當(dāng)就緒的線程分配到cpu資源時(shí)境蜕,便進(jìn)入了運(yùn)行狀態(tài)蝙场,調(diào)用run()方法,執(zhí)行業(yè)務(wù)邏輯
4粱年、阻塞:當(dāng)被人為掛起或執(zhí)行輸入輸出操作時(shí)售滤,讓出cpu時(shí)間片并臨時(shí)終止自己的執(zhí)行,進(jìn)入阻塞狀態(tài)
5逼泣、死亡:線程完成工作后趴泌、線程被強(qiáng)制退出、出現(xiàn)異常拉庶,都會(huì)導(dǎo)致線程結(jié)束嗜憔,進(jìn)入死亡狀態(tài)

線程的生命周期

8、線程同步

8.1氏仗、出現(xiàn)的問題

當(dāng)多個(gè)線程同時(shí)操作同一份共享數(shù)據(jù)時(shí)吉捶,一個(gè)線程執(zhí)行了一部分,另一個(gè)線程參與進(jìn)來皆尔,會(huì)造成共享數(shù)據(jù)的不完整性

8.2呐舔、如何解決線程共享帶來的問題

給共享數(shù)據(jù)加鎖(Synchronized),一次只能被一個(gè)線程訪問慷蠕,當(dāng)線程操作完共享數(shù)據(jù)時(shí)珊拼,釋放鎖

8.3、線程同步機(jī)制

1流炕、必須確保使用同一資源的多個(gè)線程共用一把鎖澎现,否則無法保證線程安全
2、 如果使用Runnable方式實(shí)現(xiàn)的多線程每辟,用this關(guān)鍵字剑辫,可充當(dāng)同步監(jiān)視器
3、如果使用Thread繼承方式實(shí)現(xiàn)的多線程渠欺,請用當(dāng)前類.class或者靜態(tài)對象妹蔽,充當(dāng)同步監(jiān)視器,如果使用this關(guān)鍵字的話挠将,即每個(gè)線程實(shí)例對象同時(shí)擁有自己的共享數(shù)據(jù)

8.3.1胳岂、同步代碼塊
  • 操作共享數(shù)據(jù)的代碼,即為需要被同步的代碼
  • 同步監(jiān)視器舔稀,俗稱鎖旦万,任何一個(gè)對象可以充當(dāng)鎖,多個(gè)線程必須使用同一把鎖镶蹋,否則無效
synchronized (this){
}
8.3.2、同步方法
  • Runnable實(shí)現(xiàn)方式
private synchronized void show(){//同步監(jiān)視器:this
}
  • Thread繼承方式
private static synchronized void show(){//同步監(jiān)視器:即為當(dāng)前類.calss
}
8.3.3、Lock(鎖)
  • 從JDK5.0開始贺归,Java提供Lock線程同步機(jī)制淆两,通過顯示定義同步鎖Lock對象來實(shí)現(xiàn)同步機(jī)制
  • 訪問共享資源之前,應(yīng)先取得Lock對象拂酣,在之前手動(dòng)開啟lock鎖秋冰,訪問共享資源之后,手動(dòng)關(guān)閉lock鎖
  • ReentrantLock類實(shí)現(xiàn)的Lock接口婶熬,它與synchronized一樣剑勾,都是對共享資源同步機(jī)制的訪問
使用方法
8.3.4、synchronized與Lock的區(qū)別

synchronized:
1赵颅、隱式鎖出了作用域自動(dòng)釋放
2虽另、具有同步代碼塊鎖和方法鎖,2種鎖方式
Lock:
1饺谬、顯示鎖(需手動(dòng)開啟和關(guān)閉鎖)
2捂刺、只有代碼塊鎖,沒有方法鎖
3募寨、JVM將花費(fèi)更少時(shí)間調(diào)度線程族展,性能會(huì)更好些

9、線程的死鎖

9.1拔鹰、死鎖原因

1仪缸、不同的線程分別占用對方需要的同步資源不放棄,都在等待對方釋放自己需要的同步資源列肢,就形成了死鎖
2恰画、出現(xiàn)死鎖后,并不會(huì)拋出異常和提示信息例书,所有線程處于阻塞狀態(tài)锣尉,無法繼續(xù)執(zhí)行操作

9.2、解決方案

1决采、盡量減少同步資源的定義
2自沧、盡量避免使用嵌套同步

10、線程的通信

線程與線程之間難免會(huì)相互協(xié)作去完成一件較復(fù)雜的功能树瞭,典型的例子生產(chǎn)者-消費(fèi)者

  • wait():一旦執(zhí)行此方法拇厢,當(dāng)前線程就進(jìn)入阻塞狀態(tài),并釋放同步監(jiān)視器
  • notify():一旦執(zhí)行此方法晒喷,就會(huì)喚醒被wait的一個(gè)線程孝偎。如果有多個(gè)線程被wait,就喚醒優(yōu)先級高的那個(gè)
  • notifyAll():一旦執(zhí)行此方法凉敲,就會(huì)喚醒所有被wait的線程

1衣盾、wait()寺旺,notify(),notifyAll()三個(gè)方法必須使用在同步代碼塊或同步方法中
2势决、wait()阻塑,notify(),notifyAll()三個(gè)方法的調(diào)用者必須是同步代碼塊或同步方法中的同步監(jiān)視器果复,否則會(huì)出現(xiàn)IllegalMonitorStateException異常
3陈莽、wait(),notify()虽抄,notifyAll()三個(gè)方法是定義在java.lang.Object類中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末走搁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子迈窟,更是在濱河造成了極大的恐慌私植,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件菠隆,死亡現(xiàn)場離奇詭異兵琳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)骇径,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門躯肌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人破衔,你說我怎么就攤上這事清女。” “怎么了晰筛?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵嫡丙,是天一觀的道長。 經(jīng)常有香客問我读第,道長曙博,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任怜瞒,我火速辦了婚禮父泳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吴汪。我一直安慰自己惠窄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布漾橙。 她就那樣靜靜地躺著杆融,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霜运。 梳的紋絲不亂的頭發(fā)上脾歇,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天蒋腮,我揣著相機(jī)與錄音,去河邊找鬼介劫。 笑死徽惋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的座韵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼踢京,長吁一口氣:“原來是場噩夢啊……” “哼誉碴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瓣距,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤黔帕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蹈丸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體成黄,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年逻杖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奋岁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荸百,死狀恐怖闻伶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情够话,我是刑警寧澤蓝翰,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布坷随,位于F島的核電站却桶,受9級特大地震影響万栅,放射性物質(zhì)發(fā)生泄漏他膳。R本人自食惡果不足惜砂心,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一率碾、第九天 我趴在偏房一處隱蔽的房頂上張望臼闻。 院中可真熱鬧谓罗,春花似錦媒至、人聲如沸顶别。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驯绎。三九已至,卻和暖如春谋旦,著一層夾襖步出監(jiān)牢的瞬間剩失,已是汗流浹背屈尼。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拴孤,地道東北人脾歧。 一個(gè)月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像演熟,于是被迫代替她去往敵國和親鞭执。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354