1 何為線程?
一個(gè)比進(jìn)程更小的執(zhí)行單位比吭。
與進(jìn)程不同的是:
- 同類(lèi)的多個(gè)線程共享進(jìn)程的 堆 和 方法區(qū) 資源绽族,但每個(gè)線程有自己的 程序計(jì)數(shù)器 、虛擬機(jī)棧 和 本地方法棧
2 線程與進(jìn)程的關(guān)系,區(qū)別及優(yōu)缺點(diǎn)衩藤?
- 線程是進(jìn)程劃分成的更小的運(yùn)行單位
- 同一進(jìn)程中的 線程 極有可能會(huì)相互影響吧慢,而進(jìn)程基本相互獨(dú)立
- 線程執(zhí)行開(kāi)銷(xiāo)小,但不利于資源的管理和保護(hù)
3 為什么程序計(jì)數(shù)器赏表、虛擬機(jī)棧和本地?法棧是線程私有的呢检诗?為什么堆和?法區(qū)是線程共享的呢?
- 程序計(jì)數(shù)器私有主要是為了線程切換后能恢復(fù)到正確的執(zhí)?位置瓢剿。
- 為了保證線程中的局部變量不被別的線程訪問(wèn)到逢慌,虛擬機(jī)棧(為JVM使用java方法服務(wù))和本地?法棧(為JVM使用Native方法服務(wù))是線程私有的
- 堆 ?于存放新創(chuàng)建的對(duì)象
- ?法區(qū) 主要?于存放已被加載的類(lèi)信息、常量间狂、靜態(tài)變量
4 為什么要使用多線程
目的:提高程序的執(zhí)行效率提高程序運(yùn)行速度
- 從計(jì)算機(jī)底層來(lái)說(shuō):線程間的切換和調(diào)度的成本遠(yuǎn)遠(yuǎn)小于進(jìn)程攻泼,多核 CPU 時(shí)代意味著多個(gè)線程可以同時(shí)運(yùn)行
- 從當(dāng)代互聯(lián)網(wǎng)發(fā)展趨勢(shì)來(lái)說(shuō):多線程并發(fā)編程正是開(kāi)發(fā)高并發(fā)系統(tǒng)的基礎(chǔ)
- 再深入到計(jì)算機(jī)底層來(lái)探討:
- 單核時(shí)代: 在單核時(shí)代多線程主要是為了提高 CPU 和 IO 設(shè)備的綜合利用率。
- 多核時(shí)代: 多核時(shí)代多線程主要是為了提高 CPU 利用率。
5 使用多線程可能帶來(lái)的問(wèn)題?
- 內(nèi)存泄漏
- 死鎖
- 線程不安全
6 線程的生命周期和狀態(tài)?
Java 線程在運(yùn)行的生命周期中的指定時(shí)刻只可能處于下面 6 種不同狀態(tài)的其中一個(gè)狀態(tài)
- New : 初始狀態(tài), 線程被構(gòu)建忙菠,但是還沒(méi)有調(diào)用start()方法
- Runnable : 運(yùn)行狀態(tài)何鸡,Java線程將操作系統(tǒng)中的就緒和運(yùn)行兩種狀態(tài)籠統(tǒng)地稱(chēng)作“運(yùn)行中”
- Blocked : 阻塞狀態(tài),表示線程阻塞于鎖
- Waiting :等待狀態(tài)牛欢,表示線程進(jìn)入等待狀態(tài)骡男,進(jìn)入該狀態(tài)表示當(dāng)前線程需要等待其他線程做出一些特定動(dòng)作(通知或中斷)
- Time_Waiting : 超時(shí)等待狀態(tài),該狀態(tài)不同于Waiting 氢惋,它是可以在指定的時(shí)間自行返回
- Terminated : 終止?fàn)顟B(tài)洞翩,表示當(dāng)前線程已經(jīng)執(zhí)行完畢
7 什么是上下文切換?
- 當(dāng)一個(gè)線程的時(shí)間片用完的時(shí)候就會(huì)重新處于就緒狀態(tài)讓給其他線程使用CPU,這個(gè)過(guò)程就屬于一次上下文切換焰望。
上下文切換通常是計(jì)算密集型的骚亿。也就是說(shuō),它需要相當(dāng)可觀的處理器時(shí)間熊赖,在每秒幾十上百次的切換中来屠,每次切換都需要納秒量級(jí)的時(shí)間。
8 什么是線程死鎖? 如何避免死鎖?
線程死鎖:
- 多個(gè)線程同時(shí)被阻塞震鹉,它們中的一個(gè)或者全部都在等待某個(gè)資源被釋放俱笛。由于線程被無(wú)限期地阻塞,因此程序不可能正常終止
產(chǎn)生死鎖必須具備以下四個(gè)條件:
- 互斥條件:該資源任意一個(gè)時(shí)刻只由一個(gè)線程占用传趾。
- 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí)迎膜,對(duì)已獲得的資源保持不放。
- 不剝奪條件 : 線程已獲得的資源在未使用完之前不能被其他線程強(qiáng)行剝奪浆兰,只有自己使用完畢后才釋放資源磕仅。
- 循環(huán)等待條件 : 若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。
避免線程死鎖:
- 破壞互斥條件 :這個(gè)條件我們沒(méi)有辦法破壞簸呈,因?yàn)槲覀冇面i本來(lái)就是想讓他們互斥的(臨界資源需要互斥訪問(wèn))榕订。
- 破壞請(qǐng)求與保持條件 :一次性申請(qǐng)所有的資源。
- 破壞不剝奪條件 :占用部分資源的線程進(jìn)一步申請(qǐng)其他資源時(shí)蜕便,如果申請(qǐng)不到劫恒,可以主動(dòng)釋放它占有的資源。
- 破壞循環(huán)等待條件 :靠按序申請(qǐng)資源來(lái)預(yù)防轿腺。按某一順序申請(qǐng)資源两嘴,釋放資源則反序釋放。破壞循環(huán)等待條件吃溅。
9 sleep() 方法和 wait() 方法區(qū)別和共同點(diǎn)?
- 兩者最主要的區(qū)別在于:
sleep()
方法沒(méi)有釋放鎖溶诞,而wait()
方法釋放了鎖 。 - wait() 通常被用于線程間交互/通信决侈,sleep() 通常被用于暫停執(zhí)行。
- 兩者都可以暫停線程的執(zhí)行。
10. 為什么我們調(diào)用 start() 方法時(shí)會(huì)執(zhí)行 run() 方法赖歌,為什么我們不能直接調(diào)用 run() 方法枉圃?
- 調(diào)用 start() 方法方可啟動(dòng)線程并使線程進(jìn)入就緒狀態(tài),當(dāng)分配到時(shí)間片后就可以開(kāi)始運(yùn)行了庐冯。直接執(zhí)行 run() 方法的話不會(huì)以多線程的方式執(zhí)行孽亲,而是會(huì)把它當(dāng)成mian線程下的一個(gè)普通方法去執(zhí)行。