更新時間:2020-07-09 15:04:16 來源:動力節(jié)點 瀏覽2535次
1、在java中守護線程和本地線程區(qū)別?
java中的線程分為兩種:守護線程(Daemon)和用戶線程(User)。
任何線程都可以設(shè)置為守護線程和用戶線程,通過方法Thread.setDaemon(bool on);true則把該線程設(shè)置為守護線程,反之則為用戶線程。Thread.setDaemon()必須在Thread.start()之前調(diào)用,否則運行時會拋出異常。
兩者的區(qū)別:
唯一的區(qū)別是判斷虛擬機(JVM)何時離開,Daemon是為其他線程提供服務(wù),如果全部的User Thread已經(jīng)撤離,Daemon沒有可服務(wù)的線程,JVM撤離。也可以理解為守護線程是JVM自動創(chuàng)建的線程(但不一定),用戶線程是程序創(chuàng)建的線程;比如JVM的垃圾回收線程是一個守護線程,當(dāng)所有線程已經(jīng)撤離,不再產(chǎn)生垃圾,守護線程自然就沒事可干了,當(dāng)垃圾回收線程是Java虛擬機上僅剩的線程時,Java虛擬機會自動離開。
擴展:Thread Dump打印出來的線程信息,含有daemon字樣的線程即為守護進程,可能會有:服務(wù)守護進程、編譯守護進程、windows下的監(jiān)聽Ctrl+break的守護進程、Finalizer守護進程、引用處理守護進程、GC守護進程。
2、線程與進程的區(qū)別?
進程是操作系統(tǒng)分配資源的最小單元,線程是操作系統(tǒng)調(diào)度的最小單元。
一個程序至少有一個進程,一個進程至少有一個線程。
3、什么是多線程中的上下文切換?
多線程會共同使用一組計算機上的CPU,而線程數(shù)大于給程序分配的CPU數(shù)量時,為了讓各個線程都有執(zhí)行的機會,就需要輪轉(zhuǎn)使用CPU。不同的線程切換使用CPU發(fā)生的切換數(shù)據(jù)等就是上下文切換。
4、死鎖與活鎖的區(qū)別,死鎖與饑餓的區(qū)別?
死鎖:是指兩個或兩個以上的進程(或線程)在執(zhí)行過程中,因爭奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,它們都將無法推進下去。
產(chǎn)生死鎖的必要條件:
互斥條件:所謂互斥就是進程在某一時間內(nèi)獨占資源。
請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
不剝奪條件:進程已獲得資源,在末使用完之前,不能強行剝奪。
循環(huán)等待條件:若干進程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。
活鎖:任務(wù)或者執(zhí)行者沒有被阻塞,由于某些條件沒有滿足,導(dǎo)致一直重復(fù)嘗試,失敗,嘗試,失敗。
活鎖和死鎖的區(qū)別在于,處于活鎖的實體是在不斷的改變狀態(tài),所謂的“活”,而處于死鎖的實體表現(xiàn)為等待;活鎖有可能自行解開,死鎖則不能。
饑餓:一個或者多個線程因為種種原因無法獲得所需要的資源,導(dǎo)致一直無法執(zhí)行的狀態(tài)。
Java中導(dǎo)致饑餓的原因:
高優(yōu)先級線程吞噬所有的低優(yōu)先級線程的CPU時間。
線程被永久堵塞在一個等待進入同步塊的狀態(tài),因為其他線程總是能在它之前持續(xù)地對該同步塊進行訪問。
線程在等待一個本身也處于永久等待完成的對象(比如調(diào)用這個對象的wait方法),因為其他線程總是被持續(xù)地獲得喚醒。
5、Java中用到的線程調(diào)度算法是什么?
采用時間片輪轉(zhuǎn)的方式。可以設(shè)置線程的優(yōu)先級,會映射到下層的系統(tǒng)上面的優(yōu)先級上,如非特別需要,盡量不要用,防止線程饑餓。
6、什么是線程組,為什么在Java中不推薦使用?
ThreadGroup類,可以把線程歸屬到某一個線程組中,線程組中可以有線程對象,也可以有線程組,組中還可以有線程,這樣的組織結(jié)構(gòu)有點類似于樹的形式。
為什么不推薦使用?因為使用有很多的安全隱患吧,沒有具體追究,如果需要使用,推薦使用線程池。
7、為什么使用Executor框架?
每次執(zhí)行任務(wù)創(chuàng)建線程new Thread()比較消耗性能,創(chuàng)建一個線程是比較耗時、耗資源的。
調(diào)用new Thread()創(chuàng)建的線程缺乏管理,被稱為野線程,而且可以無限制的創(chuàng)建,線程之間的相互競爭會導(dǎo)致過多占用系統(tǒng)資源而導(dǎo)致系統(tǒng)癱瘓,還有線程之間的頻繁交替也會消耗很多系統(tǒng)資源。
接使用new Thread()啟動的線程不利于擴展,比如定時執(zhí)行、定期執(zhí)行、定時定期執(zhí)行、線程中斷等都不便實現(xiàn)。
8、在Java中Executor和Executors的區(qū)別?
Executors工具類的不同方法按照我們的需求創(chuàng)建了不同的線程池,來滿足業(yè)務(wù)的需求。
Executor接口對象能執(zhí)行我們的線程任務(wù)。
ExecutorService接口繼承了Executor接口并進行了擴展,提供了更多的方法我們能獲得任務(wù)執(zhí)行的狀態(tài)并且可以獲取任務(wù)的返回值。
使用ThreadPoolExecutor可以創(chuàng)建自定義線程池。
Future表示異步計算的結(jié)果,他提供了檢查計算是否完成的方法,以等待計算的完成,并可以使用get()方法獲取計算的結(jié)果。
9、什么是原子操作?在Java Concurrency API中有哪些原子類(atomic classes)?
原子操作(atomic operation)意為”不可被中斷的一個或一系列操作”。
處理器使用基于對緩存加鎖或總線加鎖的方式來實現(xiàn)多處理器之間的原子操作。
在Java中可以通過鎖和循環(huán)CAS的方式來實現(xiàn)原子操作。CAS操作——Compare&Set,或是Compare&Swap,現(xiàn)在幾乎所有的CPU指令都支持CAS的原子操作。
原子操作是指一個不受其他操作影響的操作任務(wù)單元。原子操作是在多線程環(huán)境下避免數(shù)據(jù)不一致必須的手段。
int++并不是一個原子操作,所以當(dāng)一個線程讀取它的值并加1時,另外一個線程有可能會讀到之前的值,這就會引發(fā)錯誤。
為了解決這個問題,必須保證增加操作是原子的,在JDK1.5之前我們可以使用同步技術(shù)來做到這一點。到JDK1.5,java.util.concurrent.atomic包提供了int和long類型的原子包裝類,它們可以自動的保證對于他們的操作是原子的并且不需要使用同步。
java.util.concurrent這個包里面提供了一組原子類。其基本的特性就是在多線程環(huán)境下,當(dāng)有多個線程同時執(zhí)行這些類的實例包含的方法時,具有排他性,即當(dāng)某個線程進入方法,執(zhí)行其中的指令時,不會被其他線程打斷,而別的線程就像自旋鎖一樣,一直等到該方法執(zhí)行完成,才由JVM從等待隊列中選擇一個另一個線程進入,這只是一種邏輯上的理解。
原子類:AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference
原子數(shù)組:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
原子屬性更新器:AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater
解決ABA問題的原子類:AtomicMarkableReference(通過引入一個boolean來反映中間有沒有變過),AtomicStampedReference(通過引入一個int來累加來反映中間有沒有變過)
10、Java Concurrency API中的Lock接口(Lock interface)是什么?對比同步它有什么優(yōu)勢?
Lock接口比同步方法和同步塊提供了更具擴展性的鎖操作。
他們允許更靈活的結(jié)構(gòu),可以具有完全不同的性質(zhì),并且可以支持多個相關(guān)類的條件對象。
它的優(yōu)勢有:
可以使鎖更公平
可以使線程在等待鎖的時候響應(yīng)中斷
可以讓線程嘗試獲取鎖,并在無法獲取鎖的時候立即返回或者等待一段時間
可以在不同的范圍,以不同的順序獲取和釋放鎖
整體上來說Lock是synchronized的擴展版,Lock提供了無條件的、可輪詢的(tryLock方法)、定時的(tryLock帶參方法)、可中斷的(lockInterruptibly)、可多條件隊列的(newCondition方法)鎖操作。另外Lock的實現(xiàn)類基本都支持非公平鎖(默認(rèn))和公平鎖,synchronized只支持非公平鎖,當(dāng)然,在大部分情況下,非公平鎖是高效的選擇。
以上就是動力節(jié)點java培訓(xùn)機構(gòu)的小編針對“企業(yè)常見的Java面試題大全帶答案”的內(nèi)容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務(wù)。
相關(guān)閱讀