深入淺出java多線程(一)

昨晚看到Guide哥推送的《深入淺出Java多線程》仅父,今天一鼓作氣看了9節(jié),雖然看得很疲倦,但是對多線程的基本操作和一些原理還是有不少了解笙纤;
進(jìn)程與線程的區(qū)別開始耗溜,進(jìn)程是由操作系統(tǒng)分配內(nèi)存與其他資源(如io),線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位省容。
線程創(chuàng)建的2種方式抖拴,繼承Thread和實(shí)現(xiàn)Runnable,其中Thread使用到了裝飾者模式腥椒,裝飾Runnable對象阿宅,擴(kuò)展Runnable的功能,又使用到了策略模式笼蛛,Thread中的Runnable的各種實(shí)現(xiàn)就是一種策略洒放;
具體使用哪個可以從2個方面考慮:
1、繼承方式還是實(shí)現(xiàn)方式滨砍;
2往湿、是否需要使用Thread類的諸多方法;
這兩種線程的執(zhí)行都是沒有返回值的惨好,如果需要返回值可以使用JDK提供的Callable接口和Future接口煌茴,需要配合ExecutorService#submit(Callable c) : Future 使用随闺,返回值通過Future#get() : T 獲取日川,get()方法會阻塞當(dāng)前線程,直到得到返回結(jié)果矩乐;Future接口中定義了取消線程的cancel()方法龄句,所以如果想取消線程的話可以使用Future的實(shí)現(xiàn)類FutureTask,cancel()操作內(nèi)部實(shí)際上是執(zhí)行Thread#interrupt()方法散罕,所以調(diào)用此方法取消并不一定能取消成功分歇。
昨天總結(jié)寫的比較晚,寫到12點(diǎn)多硬是撐不住了欧漱,今天將昨天未總結(jié)完的補(bǔ)上职抡。
線程的優(yōu)先級可以調(diào)用Thread#setPriority(int i)來設(shè)置優(yōu)先級,取值范圍1~10误甚,然而并不是優(yōu)先級高的線程一定比優(yōu)先級低得先執(zhí)行缚甩,具體還是由操作系統(tǒng)決定。
線程必須存在于線程組ThreadGroup當(dāng)中窑邦,線程的優(yōu)先級不能大于所在線程組的最大優(yōu)先級擅威,如果超過將會被線程組的最大優(yōu)先級取而代之;
線程中還有一個守護(hù)線程(Deamon)冈钦,可以通過Thread#setDaemon(boolean on)來設(shè)置郊丛,只有當(dāng)所有非守護(hù)進(jìn)程結(jié)束后,守護(hù)線程才會自動結(jié)束。

接下來是線程的6種狀態(tài)以及它們之間的轉(zhuǎn)換:NEW厉熟、RUNNABLE导盅、BLOCKED、WATTING揍瑟、TIMED_WATTING认轨、TERMINATED
NEWRUNNABLE調(diào)用start(),如果有其他線程拿到鎖了月培,則進(jìn)入BLOCKED狀態(tài)嘁字;
RUNNABLEBLOCKED 等待鎖
RUNNABLEWAITING調(diào)用當(dāng)前鎖調(diào)用wait()、其他線程調(diào)用join()
RUNNABLETIMED_WAITING 調(diào)用wait(time)杉畜、join(time)纪蜒、sleep(time)
WAITING/TIMED_WAITINGRUNNABLE調(diào)用Object.notify()、notifyAll()此叠、LockSupport.unpark;
需要注意的是線程調(diào)用start()方法必定會進(jìn)入RUNNABLE狀態(tài)纯续,遇到鎖后才有可能進(jìn)入BLOCKED狀態(tài);

接下來是線程間的通信灭袁,java線程機(jī)制主要采用鎖+同步的方式來進(jìn)行線程間的通信
Synchronized:同步標(biāo)識猬错,需要一個對象做為鎖,且只能是Class對象或者Object對象茸歧;如果是靜態(tài)方法中使用這個默認(rèn)為該類.class倦炒,如果是普通方法標(biāo)記則默認(rèn)為this,同步代碼塊需要通過參數(shù)傳入鎖软瞎,如果兩段同步的鎖相同逢唤,那么線程可以從第一段同步執(zhí)行完后,直接進(jìn)入第二段同步代碼涤浇,不需要競爭鎖鳖藕,因?yàn)殒i只能被一個對象持有;
join():當(dāng)一個線程調(diào)用join后只锭,那么其他線程必須進(jìn)入WAITING等待這個線程執(zhí)行完畢后才會執(zhí)行著恩,主線程也不例外;
Object#wait()Thread#Sleep(long t)區(qū)別
1蜻展、wait()會釋放鎖喉誊,而sleep()不會;
2铺呵、wait()只有在拿到鎖的情況才能執(zhí)行裹驰,而sleep()在線程中隨時可以執(zhí)行;

接著作者提到了ThreadLocal類主要是為每個線程創(chuàng)建一個副本片挂,用來存儲線程自己的私有變量幻林;

呼啦啦贞盯,這才總結(jié)了一半,不總結(jié)還真不知道昨天學(xué)了多少知識沪饺!總結(jié)寫的好心累啊躏敢,一方面想著學(xué)習(xí)進(jìn)度,一方面手頭還有些工作要弄整葡,不管了件余,加油吧!少年遭居!

下面是原理篇啼器,主要是java內(nèi)存模型、volatile關(guān)鍵字俱萍、鎖的幾種類別端壳,先從java內(nèi)存模型講起吧,
java運(yùn)行時內(nèi)存主要由方法區(qū)枪蘑、堆损谦、虛擬機(jī)棧、本地方法棧岳颇、程序計(jì)數(shù)器這無大部分組成照捡,對于每個線程來說,堆是共有的话侧,而棧是私有的栗精,每個線程都含有一個本地內(nèi)存,保存著該線程使用的堆空間中共享變量的副本掂摔,線程只與本地內(nèi)存交互术羔,而本地內(nèi)存什么時候更新到共享內(nèi)存由虛擬機(jī)控制赢赊。線程間的通信必須通過共享內(nèi)存來進(jìn)行通信乙漓。
講到共享內(nèi)存通信,那不得不提volatile關(guān)鍵字释移,其作用主要有2個:
1叭披、內(nèi)存共享:當(dāng)一個線程對volatile修飾的變量進(jìn)行寫操作時,java運(yùn)行模型會立即把該線程對應(yīng)的本地內(nèi)存中的值刷新到主內(nèi)存中玩讳,當(dāng)一個線程對volatile修飾的變量進(jìn)行讀操作時涩蜘,java運(yùn)行模型會將本地內(nèi)存中的值設(shè)置成無效,并從主內(nèi)存中讀妊俊同诫;
2、防止指令重排樟澜;
講到volatile關(guān)鍵字不得不提單例模式雙重檢查+鎖模式误窖,其中單例變量就使用了volatile關(guān)鍵字標(biāo)記叮盘,而它的作用主要就是防止指令重排,因?yàn)閚ew Object()操作在編譯器內(nèi)有3條指令:分配內(nèi)存霹俺、初始化柔吼、賦值給變量,而如果還沒有實(shí)例化就復(fù)制給了變量丙唧,這是另一個線程剛好進(jìn)入到第一層檢查愈魏,那么就會直接返回一個未初始化完成的對象;

最后想际,了解到了同步鎖還存在升級機(jī)制培漏,而鎖的狀態(tài)也分為4種:無鎖狀態(tài)、偏向鎖胡本、輕量級鎖北苟、重量級鎖
既然講到鎖,那得弄清楚鎖存在哪個地方打瘪,鎖都是基于對象的友鼻,鎖信息存放在java對象頭中,
java對象頭占用2個字寬闺骚,如果是數(shù)組則占用3個字寬彩扔,多一個字寬用來存儲數(shù)組的長度,一個字寬對應(yīng)操作系統(tǒng)的位數(shù)僻爽,如果是64位操作系統(tǒng)中虫碉,那java對象頭就占了128位,這128位胸梆,主要存儲2種數(shù)據(jù)敦捧,hashCode+鎖信息、類型數(shù)據(jù)指針碰镜;
對象頭中就保存著鎖的狀態(tài)兢卵,線程在第一次進(jìn)入同步代碼塊時,會將線程ID保存到鎖的對象頭中绪颖,并且把鎖設(shè)置為偏向鎖的信息也保存進(jìn)去秽荤;
線程再次進(jìn)入同步代碼塊中時,會去檢查鎖對象頭里的Mark Word信息柠横,如果鎖的對象頭中Mark Word里已經(jīng)有線程ID了窃款,且線程ID等于自己時,那說明該線程已經(jīng)獲得了鎖牍氛,并且不需要花費(fèi)CAS(compare and swap)操作來進(jìn)行加鎖和解鎖晨继,那么這個鎖還是偏向鎖;
如果線程ID不等于自己的線程ID搬俊,那說明有另一個線程來競爭這把鎖了紊扬,這個時候會嘗試CAS操作來替換Mark Word里的線程ID和鎖類型曲饱,CAS操作返回成功和失敗,如果成功珠月,則表示之前線程已經(jīng)不存在了扩淀,那么替換ID,不升級鎖啤挎;如果失敗驻谆,說明之前的線程還存在,這時需要暫停之前的線程庆聘,將鎖升級為輕量級鎖(這個過程有一定開銷)胜臊;
還是剛剛那個線程,在講偏向鎖升級為輕量級鎖后伙判,會自旋競爭鎖象对,如果超過一定時間獲取不到,就會進(jìn)入阻塞狀態(tài)宴抚,CAS會將鎖升級為重量級鎖勒魔,未競爭到鎖的線程將會進(jìn)入阻塞狀態(tài),阻塞狀態(tài)不消耗CPU資源菇曲,但是線程間狀態(tài)的轉(zhuǎn)換需要相對較長的較長的時間冠绢,所以重量級鎖效率較低

呼!終于完了常潮,最后再來總結(jié)下這三種鎖的區(qū)別和使用場景吧弟胀。

1、偏向鎖:加鎖和解鎖操作不需要額外的消耗喊式,速度接近非同步方法孵户,但是線程競爭鎖導(dǎo)致鎖升級會造成額外的消耗,適用于多線程中同一時間段內(nèi)只有一個線程訪問同步代碼塊的情況岔留;
2夏哭、輕量級鎖:競爭鎖不會阻塞,提高了程序的響應(yīng)速度贸诚,但是始終得不到鎖的線程會自旋消耗CPU資源方庭,適用于追求響應(yīng)速度的情況;
3酱固、重量級鎖:線程競爭不使用自旋,不會消耗CPU头朱,但是線程阻塞运悲,響應(yīng)時間緩慢,同步塊執(zhí)行速度較長项钮,適用于追求吞吐量的情況班眯。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末希停,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子署隘,更是在濱河造成了極大的恐慌采幌,老刑警劉巖芳誓,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡凫岖,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門幢泼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渡嚣,“玉大人,你說我怎么就攤上這事脾还“槁幔” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵鄙漏,是天一觀的道長嗤谚。 經(jīng)常有香客問我,道長怔蚌,這世上最難降的妖魔是什么呵恢? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮媚创,結(jié)果婚禮上渗钉,老公的妹妹穿的比我還像新娘。我一直安慰自己钞钙,他們只是感情好鳄橘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芒炼,像睡著了一般瘫怜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上本刽,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天鲸湃,我揣著相機(jī)與錄音,去河邊找鬼子寓。 笑死暗挑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斜友。 我是一名探鬼主播炸裆,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鲜屏!你這毒婦竟也來了烹看?” 一聲冷哼從身側(cè)響起国拇,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惯殊,沒想到半個月后酱吝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡土思,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年务热,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浪漠。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡陕习,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出址愿,到底是詐尸還是另有隱情该镣,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布响谓,位于F島的核電站损合,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏娘纷。R本人自食惡果不足惜嫁审,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赖晶。 院中可真熱鬧律适,春花似錦、人聲如沸遏插。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胳嘲。三九已至厂僧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間了牛,已是汗流浹背颜屠。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹰祸,地道東北人甫窟。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像福荸,于是被迫代替她去往敵國和親蕴坪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 第6章類文件結(jié)構(gòu) 6.1 概述 6.2 無關(guān)性基石 6.3 Class類文件的結(jié)構(gòu) java虛擬機(jī)不和包括java...
    kennethan閱讀 925評論 0 2
  • 除了充分利用計(jì)算機(jī)處理器的能力外敬锐,一個服務(wù)端同時對多個客戶端提供服務(wù)則是另一個更具體的并發(fā)應(yīng)用場景背传。衡量一個服務(wù)性...
    胡二囧閱讀 1,337評論 0 12
  • 一、線程狀態(tài)轉(zhuǎn)換新建(New)可運(yùn)行(Runnable)阻塞(Blocking)無限期等待(Waiting)限期等...
    達(dá)微閱讀 577評論 1 2
  • 九種基本數(shù)據(jù)類型的大小台夺,以及他們的封裝類径玖。(1)九種基本數(shù)據(jù)類型和封裝類 (2)自動裝箱和自動拆箱 什么是自動裝箱...
    關(guān)瑋琳linSir閱讀 1,883評論 0 47
  • Java SE 基礎(chǔ): 封裝、繼承颤介、多態(tài) 封裝: 概念:就是把對象的屬性和操作(或服務(wù))結(jié)合為一個獨(dú)立的整體梳星,并盡...
    Jayden_Cao閱讀 2,108評論 0 8