Java多線程總結

在Java中引入多線程的目的顯而易見,當程序中有多部分代碼需要同時執行,這時便需要引入多線程,將需要同時執行的代碼作為線程任務(并發任務),來達到目的。

同時在這里,還有必要搞清一個問題,什么是同時執行?從字面意思來理解,就是同時執行!而事實上,是CPU瞬間在各個線程之間做著快速切換,這種切換在引入時間片技術的OS系統中,是按照時間片的技術來完成的。

在這行main函數中內容的同時,垃圾回收器的線程,同時執行!

線程創建的方式有兩種

方式一:繼承Thread類,覆蓋run()方法

步驟:

1.定義類覆蓋Thread類;

2.覆蓋Thread類中的run方法;

3.創建Thread類的子類對象創建線程對象;

4.調用線程對象的start()方法,開啟線程。


方式二:實現Runnable接口,重寫run()方法

1.定義一個類實現Runnable接口;

2.覆蓋Runnable接口中的run()方法,將線程要運行的代碼存儲到run()方法中;

3.創建該接口的子類對象;

4.通過Thread類進行線程的創建,并將Runnable接口的子類作為Thread構造參數的實參進行傳遞;

5.調用Thread類的start()開啟線程。

兩種創建方式的區別:

方式一:繼承自Thread類,這就會收到Java單繼承這種局限性的影響,當我們如果想擴展這個線程子類的功能時就會收到很大的

限制

方式二:實現Runnable接口,則可以避免方式一的局限性,極大的降低了任務對象和Thread對象的耦合,更加符合Java面向對象

編程的思想

線程安全問題

說到線程安全,我會想到售票窗口售票的情況,四個售票員同時出售這100張票,用Java程序來表示的話,就是四個線程共享一個數據,當其中一個線程在處理多條操作共享數據的過程中,其他線程參與了運算,這時就會發生線程安全問題。

線程安全的解決辦法?


只要保證一個線程在執行多條操作共享數據的語句時,其他線程不能參與運算即可,當該線程都執行完后,其他線程才可執行這些語句。

鎖--同步代碼塊,同步函數,靜態同步函數使用的鎖:


1.同步代碼塊使用的鎖是:任意的對象;

2.同步函數使用的鎖是:this,this代表當前對象的引用

3.靜態--當一個類被加載進內存以后,在我們還沒有創建對象的時候,已經有了xxx.class

靜態隨著類的加載而加載,這時內存中存儲的對象至少有一個就是該類字節碼文件對象

這個對象的表示方式:類名.class

靜態同步函數的應用場景:單例模式


單例設計模式:保證一個類在內存中只能有一個對象

怎樣才能保證對象是唯一的呢?

1.其他程序隨時用new創建該類對象,無法控制個數;

2.不讓其他程序創建,該類在本類中自己創建一個對象;

3.該類將創建的對象對位提供,讓其他程序獲取并使用。

步驟:

1.怎么實現不讓其他程序創建該類對象呢?將該類中的構造函數私有化

2.在本類中創建一個本類對象,并私有化

3.定義一個方法,返回值類型是本類類型,讓其他程序通過該方法就可以獲取本類對象

懶漢式:

class Single{

private static Single s=null;

private Single(){}

public static Single getInstance(){

if(s==null){

s=new Single();

return s;

}

}

}

在并發訪問單例的時候,懶漢式單例會被破壞,有可能不能保證對象的唯一性

例如:1線程進來后經過判斷發現為null,正在準備創建對象時,CPU切換到了2線程;

2線程進來后,經過判斷,發現也為null,正在準備創建對象時;

CPU又切換到了1線程,new Single();

此時CPU又切換到了2線程,也new Single();

這就不能保證了對象的唯一性。

解決方案?同步

class Single{

private static Single s=null;

private Single(){}

public static synchronized Single getInstance(){

if(s==null){

s=new Single();

}

return s;

}

}

但是,這樣又帶來一個新的問題:當程序中線程增多后,對鎖的判斷次數就會增多,從而影響程序的性能

那么,如何做到既保證了多線程的安全性,又可以提高程序的性能呢?那就要減少后續對鎖的判斷次數。

class Single{

private static Single s=null;

private Single(){}

private static Single getInstance(){

if(s==null){

synchronized(Single.class){

if(s=null){

s=new Single();

}

}

}

returns;

}

}

死鎖?


指多個進程or線程在運行過程中因爭奪資源而造成的一種僵局,當線程處于這種僵局時,若無外力作用,他們

無法繼續往前執行。

最常見的死鎖的情況:同步的嵌套

我們應當,盡量避免同步的嵌套情況

Thread類的方法:


run()線程中真正起作用的語句放在run()的方法體內,該方法在Thread的子類中覆蓋或在Runnable對象覆蓋

start()程序通過調用線程的start()方法執行線程,而start()則調用run()方法

sleep(long)它的一個參數指出當前執行的線程應休眠多長時間

interrupt()用于中斷一個線程

線程的生命周期



出生:新創建的線程處于出生born狀態,在調用線程的start方法之前,該線程一直處于出生狀態;

就緒:當調用start方法后,線程便進入了就緒狀態ready

運行:當系統給線程分配處理器資源時,處于就緒狀態的最高優先級線程便進入了運行狀態

死亡:當線程的run方法結束或拋出一個未捕獲的異常,那么線程便進入死亡狀態

阻塞:如果處于運行狀態的線程發出IO請求,它便進入了阻塞狀態,當其等待的IO操作結束后,阻塞的線程便進入了就緒狀態

等待:當處于運行狀態的線程調用wait方式,線程便進入等待狀態。它將按次序排在等待隊列中,隊列中的線程均是由于某個對象掉哦那個了wait方法才進入等待狀態的當與某對象相關的另一個線程調用了notify方法是,那么等待該對象所有線程都回到就緒狀態。

休眠:當程序調用一個正在運行的線程的sleep方法時,該線程便會進入休眠狀態

多線程之間的通信


多個線程在處理同一個資源,但是處理的動作(線程的任務)不同,通過一定的手段使各個線程能有效的利用資源,而這種手段就是等待喚醒機制。

等待喚醒機制所涉及到的方法:

Wait():等待,將正在執行的線程釋放其執行資格和執行權,并存儲到線程池中

Notify():喚醒,喚醒線程池中被wait()的線程,一次只能喚醒其中的任意一個

NotifyAll():喚醒全部,可以將線程池中的所有wait()線程都喚醒

其實,所謂喚醒的意思就是讓線程池中的線程具備執行資格,必須注意的是,這些方法都是在同步中有效的,同時這些方法在使用時必須標明所屬鎖,這樣才可以明確出這些方法操作的到底是哪個鎖上的線程

案例:生產者和消費者的問題

生產者生產饅頭,消費者消費饅頭….

當生產者發現沒有饅頭時,就會開始生產,生產完成后,叫消費者消費,如果發現有饅頭,就會wait();

當消費者發現沒有饅頭時,就會wait(),當發現有饅頭時,就消費,然后叫生產者繼續生產。

JDK1.5后出現的新的接口和類:Lock:比同步函數和同步代碼塊要好一些,同步函數還是同步代碼塊所做的都是隱式的操作。并且,同步函數或者同步代碼塊使用的鎖和監視器是同一個。

Lock接口:是將鎖進行單獨對象的封裝,而且提供了對鎖對象很多功能,比如:lock()獲取鎖,unlock()釋放鎖。Lock對鎖的操作都是顯示操作。所以它的出線要比同步函數或者同步代碼塊明確的多,更符合面向對象的思想

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內容

  • 一、認識多任務、多進程、單線程、多線程 要認識多線程就要從操作系統的原理說起。 以前古老的DOS操作系統(V 6....
    GT921閱讀 1,021評論 0 3
  • 一、基本的線程機制 并發編程使我們可以將程序劃分為多個分離的、獨立運行的任務。通過使用多線程機制,這些獨立任務中的...
    端木軒閱讀 514評論 0 0
  • 一:java概述:1,JDK:Java Development Kit,java的開發和運行環境,java的開發工...
    ZaneInTheSun閱讀 2,671評論 0 11
  • 多線程基礎概念介紹 進程是程序或任務的執行的過程,具有動態性;它持有資源(共享內存,共享文件)和線程;如:打開QQ...
    niaoge2016閱讀 549評論 0 2
  • 該文章轉自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,368評論 3 87