Java并發(fā)基礎

并發(fā)基礎


線程

表示一條單獨的執(zhí)行流玛臂,有自己自己單獨的程序計數(shù)器和棧;

1.1 創(chuàng)建方法

  • 繼承Thread類
  • 實現(xiàn)Runnable接口
    如果不是調用Thread.start開啟線程讽营,而是直接調用其run方法泡徙,那就不會有開啟一個新線程的作用,這種情況下堪藐,run方法只是作為一個普通方法被調用的礁竞;

1.2 基本屬性

  • id和name
    id是一個遞增的整數(shù),每創(chuàng)建一個線程就會加一寂嘉;
  • 優(yōu)先級
    Java中1-10,默認為5硼端;
    這里需要注意寓搬,設置優(yōu)先級對于操作 系統(tǒng)而言只是一個建議,編程時不要過分依賴優(yōu)先級
  • 狀態(tài)
    可以用Thread的getState()方法得到線程的狀態(tài)镣典,得到的值是一個枚舉類型唾琼,如下:

NEW:沒有調用start的線程
RUNNABLE:調用start后,正在執(zhí)行run方法并且沒有阻塞的狀態(tài)赶舆;注意:線程在運行或者具備運行條件祭饭,只是在等待操作系統(tǒng)調度
BLOCKED:線程在等待鎖倡蝙,視圖進入同步塊
WAITING: 在等待某個條件
TIMED_WAITING: 在等待超時
TERMINATED: 運行結束后的狀態(tài)

1.3 基本方法

  • isAlive()
    啟動后,run方法運行結束前猪钮,返回都是true
  • isDaemon()
    先看下什么是守護線程析既,對于一般的線程谆奥,程序在所有線程都結束后,才會退出宰译,但是對于守護線程魄懂,當整個程序剩下的都是daemon線程時市栗,就會退出咳短;
    daemon線程一般是其他線程的輔助線程
  • sleep()
    讓線程睡眠指定時間蛛淋,睡眠期間,該線程會讓出CPU勾效;
    注意:這里傳入的時間不一定會精準叛甫;
  • yield()
    該方法會建議調度器其监,目前當前線程不著急執(zhí)行,可以先讓其他線程運行
  • join()
    可以讓調用join的線程(例如主線程)等待該線程(執(zhí)行計算的子線程)執(zhí)行結束

1.4 多線程可能存在的問題

  • 競態(tài)條件:指執(zhí)行結果不確定哮奇,和執(zhí)行時序有關
    可通過synchroniezd關鍵字睛约、使用顯示鎖、使用原子變量解決
  • 內存可見性
    造成這種問題的原因是贸伐,數(shù)據(jù)會被存儲在各種高速緩存中怔揩,當訪問/修改一個變量時商膊,不一定會直接從內存中讀取/寫入,這就可能導致一個線程對值的修改藐翎,另一個線程無法及時更新到实幕;
    可以通過volatile、synchronized關鍵字或者顯示鎖方式解決

1.5 優(yōu)缺點

  • 優(yōu)點:充分利用CPU和硬件資源末贾,保證GUI及時刷新等
  • 缺點:
    創(chuàng)建線程需要耗費系統(tǒng)資源整吆,為線程創(chuàng)建程序計數(shù)器,棧等都是需要開銷的拴测;
    線程的切換也是有成本的昼扛,主要是上下文切換帶來的成本, 當切換時渺鹦,需要保存當前線程的上下文狀態(tài)(包括程序計數(shù)器的值蛹含,CPU寄存器的值等)到內存中

synchronized的理解

2.1 用法

可用于修飾類的:

  • 靜態(tài)方法
    保護的是當前的類對象
  • 實例方法
    保護的是這個實例,這里需要注意:多個線程是可以同時執(zhí)行同一個synchronized修飾的實例方法的吸耿,只要它們針對的是不同的對象即可酷窥。
    因此蓬推,需要明確一點:

synchronized修飾實例方法,保護的是當前的實例對象糕珊,即this毅糟;每一個對象都有一個鎖和等待隊列姆另,同一時間,鎖只能被一個線程所持有蜕青;具體執(zhí)行synchronized實例方法的過程如下:
1) 嘗試獲得鎖右核,若得到渺绒,則執(zhí)行菱鸥,否則氮采,加入等待隊列染苛,阻塞并等待喚醒
2) 執(zhí)行方法
3) 釋放鎖,如果等待隊列有線程躯概,則取一個并將其喚醒畔师;注意看锉,如果有多個等待線程,則喚醒哪一個是不一定的呻此,不保證公平性

  • 代碼塊
    任意對象都有一個鎖和等待隊列腔寡,也就是說任何對象都可以作為鎖對象

注意: synchronized關鍵字保護的是對象而不是具體的代碼蹬蚁,理解這一點是很重要的。只要訪問的是同一個對象的synchronized方法贝乎,即使是不同的代碼叽粹,也會被保證同步順序方法。
并且锤灿,只能保證加了synchronized修飾的方法同步執(zhí)行辆脸,synchronized方法無法保證非synchronized方法被同時執(zhí)行啡氢;因此术裸,在保護變量時亭枷,需要在所有訪問該變量的方法上加synchronized修飾叨粘。

2.2 特點

  • 可重入性:當其獲得了鎖后,當進入需要同樣鎖的代碼時答倡,可以直接進入冻晤,而無需再等待
  • 提供內存可見性:如果只是為了獲得可見性的話鼻弧,優(yōu)先考慮更加輕量的volatile關鍵字
  • 可能產生死鎖

當使用synchronized時,需要特別注意修飾的對象是否是同一個叉存,即是否使用了相同的鎖度帮;


線程間的協(xié)作

3.1 wait/notify

除了用于鎖的等待隊列笨篷, 線程還有另一個等待隊列, 表示條件隊列练俐,用于線程間的協(xié)作冕臭。
當調用了wait之后辜贵,就會把當前線程加入條件隊列并阻塞, 表示當前線程執(zhí)行不下去了鼻由,需要等待一個條件,這個條件自己改變不了跺撼,需要其他線程改變讨彼,當其他線程改變了條件后柿祈,應該調用notify方法躏嚎。

wait/notify方法只能在synchronized代碼塊內被調用,否則會拋異常重荠。

wait的具體過程

  1. 把當前的線程加入條件隊列戈鲁,釋放對象鎖嘹叫,阻塞等待,線程狀態(tài)變?yōu)閃AITING或者TIME_WAITING
  2. 等待時間到或者被其他線程調用notify/notifyAll從條件隊列中移除婆芦,這時消约,需要重新競爭對象鎖:
    a) 可以獲得员帮,線程狀態(tài)變?yōu)镽UNNABLE集侯,從wait調用中返回
    b) 無法獲得,該線程會加入對象鎖等待隊列浓体,線程狀態(tài)變?yōu)锽LOCKED辈讶,獲得鎖后才會從wait調用中返回;

從wait調用中返回后生闲,不代表其等待條件就一定成立碍讯,需要重新檢查等待條件:

synchronized (obj) {
    while(條件不成立) {
        obj.wait();
    }
    // do sth
}

調用notify后,并不會釋放對象鎖蝎困,只有在包含notify的synchronized代碼塊執(zhí)行結束后倍啥,等待的線程才會從wait調用中返回

總結:wait/notify被不同的線程調用虽缕,但是二者共享相同的鎖和條件等待隊列(即相同鎖對象的synchronized代碼塊內),二者圍繞一個共享的條件變量進行協(xié)作伍派,這個變量是程序自己維護的拙已,當不滿足時摧冀,wait并進入條件等待隊列,另一個線程修改了該條件變量并調用了notify索昂,然后調用wait的線程被喚醒建车,該線程需要重新檢查條件變量。在使用wait/notify時椒惨,需要明確協(xié)作的共享變量和條件是什么缤至。

3.2 生產者/消費者模式

Java提供的阻塞隊列有:

  • BlockingQueue
  • ArrayBlockingQueue
  • LinkedBlockingQueue等

3.3 同時開始

其他線程都先wait,條件滿足后notifyAll即可

3.4 等待結束

以未就緒線程數(shù)量為條件康谆,一個線程就緒后领斥,將條件-1,當條件為0時沃暗,notifyAll即可
Java提供了CountDownLatch用于這種情況

3.5 異步結果

Java提供的主要涉及到的是:

  • 表示異步結果的接口Future和其實現(xiàn)FutureTask
  • 用于執(zhí)行異步任務的接口Executor月洛,和具有更多功能的子接口ExecutorService
  • 創(chuàng)建上面兩種Executor的工廠類Executors

3.5 集合點

當所有線程都執(zhí)行結束后,到達集合點嚼黔,交換數(shù)據(jù)并進行下一步動作细层;這種和等待結束是類似的;
Java提供了CyclicBarrier


線程的中斷

4.1 中斷

主要用到的機制是中斷唬涧,下面來看下中斷疫赎。
中斷并不是強迫終止一個線程,它是一種協(xié)作機制碎节,是傳遞給線程一個取消信號捧搞,但何時退出是由線程來決定的。
Java主要提供了下面幾個方法:

  • isInterrupted():返回當前線程的中斷標志位是否為true
  • interrupt():中斷對應的線程
  • static interrupted():返回當前線程的中斷標志位是否為true钓株,并清空中斷標志位為false

4.2 線程對中斷的反應

根據(jù)線程當前的狀態(tài):調用interrupt()后的變化如下:

  • RUNNABLE:只是設置中斷標志位实牡,線程應該自己檢查該標志位的狀態(tài)陌僵,例如轴合,如果它是true那就應該退出循環(huán)
  • WAITING/TIMED_WAITING:會清空中斷標志位,并拋出InterruptedException碗短,該異常是受檢查異常受葛,必須處理:
    1) 向上傳遞
    2) 無法傳遞時(例如在run方法中),則需要進行合適的清理工作偎谁,并調用interrupt方法設置中斷標志位总滩,讓其他代碼知道其發(fā)生了中斷
  • BLOCKED:只是設置標志位,線程狀態(tài)不會變化巡雨。
    這里需要注意闰渔,使用synchronized關鍵字獲取鎖的過程中,不會相應中斷請求铐望,這時synchronized的局限性冈涧,如果這對程序是個問題,那就應該使用顯示鎖
  • NEW/TERMINATE:無效正蛙,標志位也不會變化

4.3 如何取消/關閉線程

如果不清楚線程在做什么督弓,不要貿然使用interrupt方法;
具體的取消方法可以參考原生實現(xiàn):Future接口的cancle()乒验、ExecutorService的shutdown()愚隧,shutdownNow()等

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锻全,隨后出現(xiàn)的幾起案子狂塘,更是在濱河造成了極大的恐慌,老刑警劉巖鳄厌,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荞胡,死亡現(xiàn)場離奇詭異,居然都是意外死亡部翘,警方通過查閱死者的電腦和手機硝训,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窖梁,你說我怎么就攤上這事赘风。” “怎么了纵刘?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵邀窃,是天一觀的道長。 經常有香客問我假哎,道長瞬捕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任舵抹,我火速辦了婚禮肪虎,結果婚禮上,老公的妹妹穿的比我還像新娘惧蛹。我一直安慰自己扇救,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布香嗓。 她就那樣靜靜地躺著迅腔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪靠娱。 梳的紋絲不亂的頭發(fā)上沧烈,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音像云,去河邊找鬼锌雀。 笑死,一個胖子當著我的面吹牛苫费,可吹牛的內容都是我干的汤锨。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼百框,長吁一口氣:“原來是場噩夢啊……” “哼闲礼!你這毒婦竟也來了?” 一聲冷哼從身側響起铐维,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤柬泽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嫁蛇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锨并,經...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年睬棚,在試婚紗的時候發(fā)現(xiàn)自己被綠了第煮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片解幼。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖包警,靈堂內的尸體忽然破棺而出撵摆,到底是詐尸還是另有隱情,我是刑警寧澤害晦,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布特铝,位于F島的核電站,受9級特大地震影響壹瘟,放射性物質發(fā)生泄漏鲫剿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一稻轨、第九天 我趴在偏房一處隱蔽的房頂上張望灵莲。 院中可真熱鬧,春花似錦澄者、人聲如沸笆呆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至俄精,卻和暖如春询筏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背竖慧。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工嫌套, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人圾旨。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓踱讨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親砍的。 傳聞我的和親對象是個殘疾皇子痹筛,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容