Java基礎(chǔ)知識之線程基礎(chǔ)

一、 概念問答

問:什么是進程驱还?
答: 進程是操作系統(tǒng)進行資源(cpu,內(nèi)存空間,磁盤IO)分配的最小單位,進程與進程之前相互獨立义锥。

問:什么是線程?
答: 線程是指進程中的一個執(zhí)行流程,一個進程可以運行多個線程。Java中線程是指java.lang.Thread類的一個實例碉熄。 線程是CPU調(diào)動的最小單位,不能獨立于進程存在肋拔。啟動一個應(yīng)用程序锈津,必然至少有一個線程。真正執(zhí)行任務(wù)的是線程凉蜂。(為了合理分配資源琼梆,一般情況下每個進程都會有最大線程數(shù)。Linux 一個進程中最多可以開1000個線程窿吩;Window 一個進程中最多可以開1200個線程茎杂。

問:線程和進程之間的關(guān)系?
答: 一個進程可以有多個線程纫雁,在同一個進程中蛉顽,線程可以共享該進程的資源(cpu,內(nèi)存,磁盤···)。

問:CPU核心數(shù)和線程數(shù)的關(guān)系先较?
答: 一般情況下携冤,核心數(shù)和線程數(shù)是一比一的關(guān)系,即在同一個時間內(nèi)闲勺,一個內(nèi)核只能運行一個線程曾棕。那么問題來了:我們平時在開發(fā)中,經(jīng)常會開很多個線程菜循,那么這又是怎么回事呢?此時就需要引入另外一個概念:CPU時間片輪轉(zhuǎn)機制翘地,也叫RR調(diào)度

問:什么是CPU時間片輪轉(zhuǎn)機制?
答: 將CPU的時間進行切片癌幕,每個進程分配一個時間段衙耕;然后CPU輪流去執(zhí)行某個時間段。(一般情況下CPU執(zhí)行一個指令的時間是0.6納秒(1s=10億納秒)勺远;普通人的時間感知為0.1s,所以CPU在切換時間片的時候橙喘,我們是無法感知的,因此給我們的錯覺就是胶逢,每個任務(wù)都是連續(xù)執(zhí)行的厅瞎。這就是為什么我們可以開大于內(nèi)核數(shù)量的線程的原因

問:什么叫并行?
答: 可以同時運行的任務(wù)數(shù)初坠,叫并行和簸。
例如:8核CPU,在同一時間點可以同時執(zhí)行8個任務(wù)碟刺。

問:什么叫并發(fā)量锁保?
答:單位時間內(nèi),能夠執(zhí)行的任務(wù)數(shù)。
例如:1核CPU爽柒,在1秒鐘之內(nèi)吴菠,可以執(zhí)行100個任務(wù);他的并發(fā)量就是100霉赡。

問:什么叫多線程開發(fā)?
答: 顧名思義幔托,在同一個進程(應(yīng)用)中同時運行多個線程穴亏。使用多線程開發(fā)的好處就是,使代碼模塊化重挑,異步化嗓化,簡單化。與之相對的壞處就是容易出現(xiàn)線程安全問題谬哀。

問:線程安全是什么刺覆?安全線程又是什么?
答:

  • 線程安全就是線程同步的意思史煎,就是當(dāng)一個程序?qū)σ粋€線程安全的方法或者語句進行訪問的時候谦屑,其他的不能再對他進行操作了,必須等到這次訪問結(jié)束以后才能對這個線程安全的方法進行訪問篇梭。
  • 安全線程就是氢橙,如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼恬偷。如果每次運行結(jié)果和單線程運行的結(jié)果是一樣的悍手,而且其他的變量的值也和預(yù)期的是一樣的,說明這些線程就是安全的袍患。

問:什么情況下可能出現(xiàn)線程安全坦康?
答: 當(dāng)線程與線程之間存在資源競爭的時候,容易出現(xiàn)線程安全問題诡延。

問:如何解決線程安全問題滞欠?
答: 使用鎖(synchronized,volatile)肆良。

問:如何啟動一個線程
答: 啟動線程有兩種方式:Thread和Runnable(JDK官方明確提出仑撞,啟動線程的方法只有兩種);
Thread用法:

//創(chuàng)建一個線程對象
class Thread1 extends Thread{ 
    public void run() {  
       //do something
    }  
}  

//調(diào)用類
public class Main {
    public static void main(String[] args) {
        //啟動線程
    new Thread1().start();
    }
}

Runnable用法:

//實現(xiàn) Runnable接口
public class Thread2 implements Runnable{
    public void run() {
        //do someThing
    }
  }

//調(diào)用類
public class Main {
    public static void main(String[] args) {
        //啟動線程2
    new Thread(new Thread2()).start();
    }
}

問:Thread和Runnable的區(qū)別是什么妖滔?
答: 在Java中隧哮,Thread是對線程的抽象;而Runnable是對任務(wù)(業(yè)務(wù)邏輯)的抽象

問:啟動線程后座舍,又該如何停止線程呢沮翔?
答: 使用suspend(),stop(),interrupt(),isInterrupted()和靜態(tài)方法interred()

  • suspend()掛起:讓一個線程進行一次上下文切換,使其從可運行狀態(tài),轉(zhuǎn)變?yōu)閽炱馉顟B(tài)采蚀。此時不會釋放資源也不會釋放鎖疲牵。占著資源和鎖進入到睡眠狀態(tài),容易引發(fā)死鎖問題榆鼠。官方不建議使用纲爸,已廢棄!
  • stop()停止:強制干掉當(dāng)前線程妆够,可能會造成當(dāng)前線程資源無法釋放识啦,也可能會文件寫到一半時突然中止,導(dǎo)致文件不完整神妹。該方法過于暴力颓哮,官方不建議使用,已廢棄鸵荠!
  • interrupt()中斷:對線程發(fā)起中斷冕茅,標(biāo)識該線程應(yīng)該被中斷了,而非立即中斷蛹找。非強制性姨伤!線程可以忽視該標(biāo)識。
  • isInterrupted()是否中斷:檢查當(dāng)前線程是否被中斷
  • static interrupted():檢查當(dāng)前線程是否被中斷庸疾,然后將中斷標(biāo)識修改為false姜挺;

問:什么是守護線程?
答: 守護線程是指為其他線程服務(wù)的線程彼硫。在JVM中炊豪,所有非守護線程都執(zhí)行完畢后,無論有沒有守護線程拧篮,虛擬機都會自動退出词渤。因此,JVM退出時串绩,不必關(guān)心守護線程是否已結(jié)束缺虐。

二、Thread詳解(Android API 27版本)

根據(jù)上面的知識點我們知道礁凡,Thread類是Java中對線程的唯一抽象高氮。那么我們對這個Thread類是否足夠了解呢?接下來我們就來仔細(xì)探討一下這個Thread類顷牌。

線程是什么剪芍,我們已經(jīng)知道了:線程是進程中的一個執(zhí)行流程。既然是執(zhí)行流程窟蓝,那就有開始和結(jié)束罪裹;那么線程從開始到結(jié)束究竟是如何的呢?我們看下圖:


image.png

從上圖可知,一個完整的線程總共5個狀態(tài),分別是:新建状共、就緒套耕、運行、阻塞峡继、死亡冯袍。那么這時候就有個疑問了,為什么start()之后沒有直接進入運行狀態(tài)碾牌,而是到了就緒狀態(tài)呢康愤?這就是因為有CPU時間片輪轉(zhuǎn)機制,當(dāng)start()之后小染,線程進入到就緒狀態(tài)(可運行狀態(tài))翘瓮,只有當(dāng)CPU給該線程分配了運行時間(獲得執(zhí)行權(quán))贮折,該線程才能進入到運行狀態(tài)裤翩。
每個狀態(tài)都對應(yīng)著一定的操作,接下來我們來看看這些操作是什么意思调榄,有什么作用:

start(): 啟動線程

通過觀察圖片上的源碼踊赠,我們可以得到如下幾個信息:

  • 在716行的注釋中This method is not invoked for the main method thread or "system" 這句話表明,方法不會被主線程或者系統(tǒng)線程調(diào)用每庆,因此該方法就是專門給我們開發(fā)者使用的筐带。

  • 在 723行和724行這兩行代碼表明:一個線程只能啟動一次,多次啟動會拋狀態(tài)異常!
  • 733行:這一行是真正啟動線程的代碼缤灵。這是一個native方法

join(): 該方法的作用就是同步伦籍,它可以使并行執(zhí)行的線程改為順序執(zhí)行。也可以改變線程的執(zhí)行順序腮出。比如帖鸦,當(dāng)前正在執(zhí)行main線程,此時a線程調(diào)用了join()函數(shù)胚嘲,那么main函數(shù)就會放棄當(dāng)前cpu的控制權(quán)作儿,并返回a線程繼續(xù)執(zhí)行,直到a線程執(zhí)行完成馋劈,才執(zhí)行main線程攻锰。具體代碼如下:

如果不調(diào)用join()函數(shù),執(zhí)行結(jié)果如下:

會先執(zhí)行main線程妓雾,main線程執(zhí)行結(jié)束之后娶吞,然后執(zhí)行A線程,A線程執(zhí)行結(jié)束之后械姻,然后執(zhí)行B線程寝志。

調(diào)用join()函數(shù)之后:

因為在main線程中執(zhí)行了threadA.join(),所以main線程進入就緒狀態(tài),線程A開始執(zhí)行,此時在線程A中又調(diào)用了threadB.join(),所以線程A也進入到了就緒狀態(tài)材部,線程B開始執(zhí)行毫缆;當(dāng)線程B執(zhí)行完成之后,線程A才能繼續(xù)執(zhí)行乐导。線程A執(zhí)行完成之后苦丁,main線程才能繼續(xù)執(zhí)行。這樣就達(dá)到了改變線程的執(zhí)行順序的目的物臂。

yield: 讓當(dāng)前(調(diào)用yeild())的線程讓出CPU的占有權(quán)旺拉,當(dāng)前線程進入到就緒 狀態(tài)。操作系統(tǒng)重新分配CPU使用權(quán)(此時雖然讓出了CPU的使用權(quán)棵磷,但是不會釋放鎖)蛾狗。此時當(dāng)前線程依然可能被分配到CPU的使用權(quán),從而重新進入到運行狀態(tài)仪媒。

sleep():

wait():

interrupt(): 對線程發(fā)起中斷沉桌,標(biāo)識該線程應(yīng)該被中斷了,而非立即中斷算吩。非強制性留凭!線程可以忽視該標(biāo)識。

stop(): 強制干掉當(dāng)前線程偎巢,可能會造成當(dāng)前線程資源無法釋放蔼夜,也可能會文件寫到一半時突然中止,導(dǎo)致文件不完整压昼。該方法過于暴力求冷,官方不建議使用,已廢棄窍霞!

notify():

notifyAll():

setDaemon(boolean on) 將線程標(biāo)記為守護線程匠题。使用方法:

Thread t = new Thread();
t.setDaemon(true);//setDaemon(),在start()之前調(diào)用
t.start();

三、線程安全

synchrond: synchronied關(guān)鍵字也就是我們所謂的鎖官撼,為了保證線程安全梧躺,經(jīng)常會用到它。synchronized鎖的內(nèi)容主要是對象傲绣,所以稱之為對象鎖掠哥,也叫內(nèi)置鎖。其主要用法如下:


在同一個實例中秃诵,多個線程同時調(diào)用funName1()和funName2():

輸出結(jié)果為:順序執(zhí)行

結(jié)論:funName()1和funName2(),持有的是同一把鎖

在同一個實例中续搀,多個線程同時調(diào)用funName2()和funName3():

輸出結(jié)果為:同時執(zhí)行

結(jié)論:funName()2和funName3(),持有的是不同的鎖

多個線程同時調(diào)用 static funName4()

輸出結(jié)果為:順序執(zhí)行

結(jié)論:在全局任何地方調(diào)用都是持有的同一把鎖

volatile:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市菠净,隨后出現(xiàn)的幾起案子禁舷,更是在濱河造成了極大的恐慌彪杉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牵咙,死亡現(xiàn)場離奇詭異派近,居然都是意外死亡,警方通過查閱死者的電腦和手機洁桌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門渴丸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人另凌,你說我怎么就攤上這事谱轨。” “怎么了吠谢?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵土童,是天一觀的道長。 經(jīng)常有香客問我工坊,道長献汗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任栅组,我火速辦了婚禮雀瓢,結(jié)果婚禮上枢析,老公的妹妹穿的比我還像新娘玉掸。我一直安慰自己,他們只是感情好醒叁,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布司浪。 她就那樣靜靜地躺著,像睡著了一般把沼。 火紅的嫁衣襯著肌膚如雪啊易。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天饮睬,我揣著相機與錄音租谈,去河邊找鬼。 笑死捆愁,一個胖子當(dāng)著我的面吹牛割去,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播昼丑,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼呻逆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了菩帝?” 一聲冷哼從身側(cè)響起咖城,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤茬腿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宜雀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體切平,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年辐董,在試婚紗的時候發(fā)現(xiàn)自己被綠了揭绑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡郎哭,死狀恐怖他匪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情夸研,我是刑警寧澤邦蜜,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站亥至,受9級特大地震影響悼沈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜姐扮,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一絮供、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茶敏,春花似錦壤靶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恬惯,卻和暖如春向拆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酪耳。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工浓恳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碗暗。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓颈将,卻偏偏與公主長得像,于是被迫代替她去往敵國和親讹堤。 傳聞我的和親對象是個殘疾皇子吆鹤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

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