新聞中心
1.什么是進程?
是一個具有一定獨立功能的程序在一個數(shù)據(jù)集上的一次動態(tài)執(zhí)行的過程,是操作系統(tǒng)進行資源分配和調(diào)度的一個獨立單位,是應(yīng)用程序運行的載體。
成都創(chuàng)新互聯(lián)專注于江口網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供江口營銷型網(wǎng)站建設(shè),江口網(wǎng)站制作、江口網(wǎng)頁設(shè)計、江口網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)服務(wù),打造江口網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供江口網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
?
2.什么是線程?
線程是操作系統(tǒng)能夠進行運算調(diào)度的最小單位。
它被包含在進程之中,是進程中的實際運作單位。
一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務(wù)。
?
3.進程和線程的區(qū)別?
進程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。
進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響。
線程只是一個進程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。
但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進程。
?
4.多線程和單線程有什么區(qū)別?
單線程程序:程序執(zhí)行過程中只有一個有效操作的序列,不同操作之間都有明確的執(zhí)行先后順序,容易出現(xiàn)代碼阻塞
多線程程序:有多個線程,線程間獨立運行,能有效地避免代碼阻塞,并且提高程序的運行性能
?
5.為什么要使用多線程?
(1)使用多線程可以減少程序的響應(yīng)時間。 在單線程的情況下,如果某個程序很耗時或者陷入長時間等待(如等待網(wǎng)絡(luò)響應(yīng)),此時程序?qū)⒉粫鄳?yīng)鼠標(biāo)和鍵盤等操作,使用多線程后,可以把這個耗時的線程分配到一個單獨的線程去執(zhí)行,從而是程序具備了更好的交互性。
(2)與進程相比,線程的創(chuàng)建和切換開銷更小。 由于啟動一個新的線程必須給這個線程分配獨立的地址空間,建立許多數(shù)據(jù)結(jié)構(gòu)來維護線程代碼段、數(shù)據(jù)段等信息,而運行于同一個進程內(nèi)的線程共享代碼段、數(shù)據(jù)段,線程的啟動或切換的開銷就比進程要少很多。同時多線程在數(shù)據(jù)共享方面效率非常高。
(3)多CPU或多核心計算機本身就具有執(zhí)行多線程的能力。 如果使用單個線程,將無法重復(fù)利用計算機資源,造成資源的巨大浪費。因此在多CPU計算機上使用多線程能提高CPU的利用率。
(4)使用多線程能簡化程序的結(jié)構(gòu),使用程序便于理解和維護。 一個非常復(fù)雜的進程可以分成多個線程來執(zhí)行。
?
6.什么是線程安全?
當(dāng)多個線程訪問同一個對象時,如果不用考慮這些線程在運行時環(huán)境下的調(diào)度和交替運行,也不需要進行額外的同步,或者在調(diào)用方進行任何其他的協(xié)調(diào)操作,調(diào)用這個對象的行為都可以獲取正確的結(jié)果,那這個對象是線程安全的。 ——<<深入Java虛擬機>>
?
7.為何要使用線程同步?
Java允許多線程并發(fā)控制,當(dāng)多個線程同時操作一個可共享的資源變量時(如數(shù)據(jù)的增刪改查),將會導(dǎo)致數(shù)據(jù)不準(zhǔn)確,相互之間產(chǎn)生沖突。
因此加入同步鎖以避免在該線程沒有完成操作之前,被其他線程的調(diào)用,從而保證了該變量的唯一性和準(zhǔn)確性。
?
8.如何確保線程安全?
對非安全的代碼進行加鎖控制
使用線程安全的類
多線程并發(fā)情況下,線程共享的變量改為方法級的局部變量
?
9.什么是原子操作?
檢查數(shù)值、改變數(shù)值,以及可能發(fā)生的睡眠操作均作為單一的、不可分割的原子操作完成。
?
10Java內(nèi)存模型是什么?
Java中所有變量都儲存在主存中,對于所有線程都是共享的(因為在同一進程中),每個線程都有自己的工作內(nèi)存或本地內(nèi)存(Working Memory),工作內(nèi)存中保存的是主存中某些變量的拷貝,線程對所有變量的操作都是在工作內(nèi)存中進行,而線程之間無法相互直接訪問,變量傳遞均需要通過主存完成,但是在程序內(nèi)部可以互相調(diào)用(通過對象方法),所有線程間的通信相對簡單,速度也很快。?
2、進程間的內(nèi)部數(shù)據(jù)和狀態(tài)都是相互完全獨立的,因此進程間通信大多數(shù)情況是必須通過網(wǎng)絡(luò)實現(xiàn)。線程本身的數(shù)據(jù),通常只有寄存器數(shù)據(jù),以及一個程序執(zhí)行時使用的堆棧,所以線程的切換比進程切換的負(fù)擔(dān)要小。
3、CPU對于各個線程的調(diào)度是隨機的(分時調(diào)度),在Java程序中,JVM負(fù)責(zé)線程的調(diào)度。 線程調(diào)度是指按照特定的機制為多個線程分配CPU的使用權(quán),也就是實際執(zhí)行的時候是線程,因此CPU調(diào)度的最小單位是線程,而資源分配的最小單位是進程。
?
11.Java中堆和棧有什么不同?
棧:在函數(shù)中定義的基本類型的變量和對象的引用變量都是在函數(shù)的棧內(nèi)存中分配。
堆:堆內(nèi)存用于存放由new創(chuàng)建的對象和數(shù)組。
從通俗化的角度來說,堆是用來存放對象的,棧是用來存放執(zhí)行程序的
?
12.JVM中哪個參數(shù)是用來控制線程的棧堆棧小的
-Xss參數(shù)用來控制線程的堆棧大小。
?
13.什么是競態(tài)條件?你怎樣發(fā)現(xiàn)和解決競爭?
當(dāng)兩個線程競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態(tài)條件。
在臨界區(qū)中使用適當(dāng)?shù)耐骄涂梢员苊飧倯B(tài)條件。
界區(qū)實現(xiàn)方法有兩種,一種是用synchronized,一種是用Lock顯式鎖實現(xiàn)。
?
14.線程安全的級別
不可變
不可變的對象一定是線程安全的,并且永遠(yuǎn)也不需要額外的同步。
Java類庫中大多數(shù)基本數(shù)值類如Integer、String和BigInteger都是不可變的。
?
15.無條件的線程安全
由類的規(guī)格說明所規(guī)定的約束在對象被多個線程訪問時仍然有效,不管運行時環(huán)境如何排列,線程都不需要任何額外的同步。
如 Random 、ConcurrentHashMap、Concurrent集合、atomic
?
16有條件的線程安全
有條件的線程安全類對于單獨的操作可以是線程安全的,但是某些操作序列可能需要外部同步。
有條件線程安全的最常見的例子是遍歷由 Hashtable 或者 Vector 或者返回的迭代器
?
17.非線程安全(線程兼容)
線程兼容類不是線程安全的,但是可以通過正確使用同步而在并發(fā)環(huán)境中安全地使用。
如ArrayList HashMap
?
18.線程對立
線程對立是那些不管是否采用了同步措施,都不能在多線程環(huán)境中并發(fā)使用的代碼。
如如System.setOut()、System.runFinalizersOnExit()
?
19.你對線程優(yōu)先級的理解是什么?
每一個線程都是有優(yōu)先級的,一般來說,高優(yōu)先級的線程在運行時會具有優(yōu)先權(quán),但這依賴于線程調(diào)度的實現(xiàn),這個實現(xiàn)是和操作系統(tǒng)相關(guān)的(OSdependent)。
可以定義線程的優(yōu)先級,但是這并不能保證高優(yōu)先級的線程會在低優(yōu)先級的線程前執(zhí)行。線程優(yōu)先級是一個int變量(從1-10),1代表最低優(yōu)先級,10代表最高優(yōu)先級。
?
20.什么是線程調(diào)度器(Thread Scheduler)和時間分片(Time Slicing)?
線程調(diào)度器是一個操作系統(tǒng)服務(wù),它負(fù)責(zé)為Runnable狀態(tài)的線程分配CPU時間。一旦創(chuàng)建一個線程并啟動它,它的執(zhí)行便依賴于線程調(diào)度器的實現(xiàn)。
時間分片是指將可用的CPU時間分配給可用的Runnable線程的過程。分配CPU時間可以基于線程優(yōu)先級或者線程等待的時間。
線程調(diào)度并不受到Java虛擬機控制,所以由應(yīng)用程序來控制它是更好的選擇。
?
21.在多線程中,什么是上下文切換(context-switching)?
單核CPU也支持多線程執(zhí)行代碼,CPU通過給每個線程分配CPU時間片來實現(xiàn)這個機制。時間片是CPU分配給各個線程的時間,因為時間片非常短,所以CPU通過不停地切換線程執(zhí)行,讓我們感覺多個線程時同時執(zhí)行的,時間片一般是幾十毫秒(ms)。
操作系統(tǒng)中,CPU時間分片切換到另一個就緒的線程,則需要保存當(dāng)前線程的運行的位置,同時需要加載需要恢復(fù)線程的環(huán)境信息。
?
22.用戶線程和守護線程有什么區(qū)別?
守護線程都是為JVM中所有非守護線程的運行提供便利服務(wù): 只要當(dāng)前JVM實例中尚存在任何一個非守護線程沒有結(jié)束,守護線程就全部工作;只有當(dāng)最后一個非守護線程結(jié)束時,守護線程隨著JVM一同結(jié)束工作。
User和Daemon兩者幾乎沒有區(qū)別,唯一的不同之處就在于虛擬機的離開:如果 User Thread已經(jīng)全部退出運行了,只剩下Daemon Thread存在了,虛擬機也就退出了。
因為沒有了被守護者,Daemon也就沒有工作可做了,也就沒有繼續(xù)運行程序的必要了。
?
23.如何創(chuàng)建守護線程?以及在什么場合來使用它?
任何線程都可以設(shè)置為守護線程和用戶線程,通過方法Thread.setDaemon(bool on);true則把該線程設(shè)置為守護線程,反之則為用戶線程。Thread.setDaemon()必須在Thread.start()之前調(diào)用,否則運行時會拋出異常。
守護線程相當(dāng)于后臺管理者 比如 : 進行內(nèi)存回收,垃圾清理等工作
?
24.線程的狀態(tài)轉(zhuǎn)換?
1、新建狀態(tài)(New):新創(chuàng)建了一個線程對象。
2、就緒狀態(tài)(Runnable):線程對象創(chuàng)建后,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運行線程池中,變得可運行,等待獲取CPU的使用權(quán)。
3、運行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。
4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因為某種原因放棄CPU使用權(quán),暫時停止運行。直到線程進入就緒狀態(tài),才有機會轉(zhuǎn)到運行狀態(tài)。阻塞的情況分三種: (一)、等待阻塞:運行的線程執(zhí)行wait()方法,JVM會把該線程放入等待池中。(wait會釋放持有的鎖) (二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。 (三)、其他阻塞:運行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時,JVM會把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)。(注意,sleep是不會釋放持有的鎖)
5、死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。
?
25.線程中斷是否能直接調(diào)用stop,為什么?
Java提供的終止方法只有一個stop,但是不建議使用此方法,因為它有以下三個問題:
stop方法是過時的 從Java編碼規(guī)則來說,已經(jīng)過時的方式不建議采用.
stop方法會導(dǎo)致代碼邏輯不完整 stop方法是一種”惡意”的中斷,一旦執(zhí)行stop方法,即終止當(dāng)前正在運行的線程,不管線程邏輯是否完整,這是非常危險的.
?
本文名稱:25道多線程面試題(一)
當(dāng)前路徑:http://fisionsoft.com.cn/article/jdigcg.html