標籤:tab 資料庫 程式啟動 where 定義 擴充性 tar 提升 代碼
Hibernate的緩衝機制
1、Hibernate是一個持久層架構,經常訪問物理資料庫,為了降低應用程式對物理資料來源訪問的頻次,從而提高應用程式的運行效能。
緩衝內的資料是對物理資料來源中的資料的複製,應用程式在運行時從緩衝讀寫資料,在特定的時刻或事件會同步緩衝和物理資料來源的資料。
2、Hibernate一級緩衝又稱為“Session的緩衝”,它是內建的,不能被卸載(不能被卸載的意思就是這種緩衝不具有可選性,
必須有的功能,不可以取消session緩衝)。
由於Session對象的生命週期通常對應一個資料庫事務或者一個應用事務,因此它的緩衝是事務範圍的緩衝。
3、Hibernate二級緩衝又稱為“SessionFactory的緩衝”,由於SessionFactory對象的生命週期和應用程式的整個過程對應,
因此Hibernate二級緩衝是進程範圍或者叢集範圍的緩衝,有可能出現並發問題,因此需要採用適當的並發存取原則,
該策略為被緩衝的資料提供了交易隔離等級。
4、無論何時,我們在管理Hibernate緩衝(Managing the caches)時,當你給save()、update()或saveOrUpdate()方法傳遞一個對象時,
或使用load()、 get()、list()、iterate() 或scroll()方法獲得一個對象時, 該對象都將被加入到Session的內部緩衝中。
2、什麼是線程,線程和進程的區別 ,java如何?線程
線程是作業系統能夠進行運算調度的最小單位,它被包含在進程之中,是進程中的實際運作單位。
區別:線程是進程的子集,一個進程可以有很多線程,每條線程並存執行不同的任務。不同的進程使用不同的記憶體空間,而所有的線程共用一片相同的記憶體空間。每個線程都擁有單獨的棧記憶體用來儲存本機資料。
實現線程:繼承Thread或實現Runnable介面 ;這兩種方法都能實現線程 區別是 java 不支援類的多重繼承, 但允許調用多個介面,如果要繼承其他類 只能調用Runnable介面
3、 Thread 類中的start() 和 run() 方法有什麼區別?
start()方法被用來啟動新建立的線程,而且start內部調用了run()方法,這和直接調用run()方法的效果不一樣。當你調用run()方法的時候,
只會是在原來的線程中調用,沒有新的線程啟動,start()方法才會啟動新線程。
4、Java中的volatile 變數是什嗎?
volatile是一個特殊的修飾符,只有成員變數才能使用它。在Java並發程式缺少同步類的情況下,多線程對成員變數的操作對其它線程是透明的。
volatile變數可以保證下一個讀取操作會在前一個寫操作之後發生
5、什麼是安全執行緒?Vector是一個安全執行緒類嗎?
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程啟動並執行結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是安全執行緒的。一個安全執行緒的計數器類的同一個執行個體對象在被多個線程使用的情況下也不會出現計算失誤。
Vector 是用同步方法來實現安全執行緒的, 而和它相似的ArrayList不是安全執行緒的。
6、Java中如何停止一個線程?
Java提供了很豐富的API但沒有為停止線程提供API。
JDK 1.0本來有一些像stop(), suspend() 和 resume()的控制方法但是由於潛在的死結威脅因此在後續的JDK版本中他們被棄用了,
之後Java API的設計者就沒有提供一個相容且安全執行緒的方法來停止一個線程。
當run() 或者 call() 方法執行完的時候線程會自動結束,如果要手動結束一個線程,你可以用volatile 布爾變數來退出run()方法的迴圈或者是取消任務來中斷線程。
7、一個線程運行時發生異常會怎樣?
如果異常沒有被捕獲該線程將會停止執行。Thread.UncaughtExceptionHandler是用於處理未捕獲異常造成線程突然中斷情況的一個內嵌介面。
當一個未捕獲異常將造成線程中斷的時候JVM會使用Thread.getUncaughtExceptionHandler()來查詢線程的UncaughtExceptionHandler並將線程和異常作為參數傳遞給handler的uncaughtException()方法進行處理。
8、Java中notify 和 notifyAll有什麼區別?
因為多線程可以等待單監控鎖,Java API 的設計人員提供了一些方法當等待條件改變的時候通知它們,但是這些方法沒有完全實現。
notify()方法不能喚醒某個具體的線程,所以只有一個線程在等待的時候它才有用武之地。
而notifyAll()喚醒所有線程並允許他們爭奪鎖確保了至少有一個線程能繼續運行。
9、為什麼wait, notify 和 notifyAll這些方法不在thread類裡面?
一個很明顯的原因是JAVA提供的鎖是對象級的而不是線程級的,每個對象都有鎖,通過線程獲得。
如果線程需要等待某些鎖那麼調用對象中的wait()方法就有意義了。如果wait()方法定義在Thread類中,線程正在等待的是哪個鎖就不明顯了。
簡單的說,由於wait,notify和notifyAll都是鎖層級的操作,所以把他們定義在Object類中因為鎖屬於對象。
10、Java中的同步集合與並發集合有什麼區別?
同步集合與並發集合都為多線程和並發提供了合適的安全執行緒的集合,不過並發集合的可擴充性更高。
並發集合像ConcurrentHashMap,不僅提供安全執行緒還用鎖分離和內部分區等現代技術提高了可擴充性。
11、Java中堆和棧有什麼不同?
每個線程都有自己的棧記憶體,用於儲存本地變數,方法參數和棧調用,一個線程中儲存的變數對其它線程是不可見的。
而堆是所有線程共用的一片公用記憶體地區。對象都在堆裡建立,為了提升效率線程會從堆中弄一個緩衝到自己的棧,如果多個線程使用該變數就可能引發問題,這時volatile 變數就可以發揮作用了,它要求線程從主存中讀取變數的值。
12、什麼是線程池? 為什麼要使用它?
建立線程要花費昂貴的資源和時間,如果任務來了才建立線程那麼回應時間會變長,而且一個進程能建立的線程數有限。
為了避免這些問題,在程式啟動的時候就建立若干線程來響應處理,它們被稱為線程池,裡面的線程叫背景工作執行緒。從JDK1.5開始,Java API提供了Executor架構讓你可以建立不同的線程池。比如單線程池,每次處理一個任務;數目固定的線程池或者是緩衝線程池(一個適合很多生存期短的任務的程式的可擴充線程池)。
13、如何避免死結?
Java多線程中的死結死結是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。
死結的發生必須滿足以下四個條件:
互斥條件:一個資源每次只能被一個進程使用。
請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
迴圈等待條件:若干進程之間形成一種頭尾相接的迴圈等待資源關係。
避免死結最簡單的方法就是阻止迴圈等待條件,將系統中所有的資源設定標誌位、排序,規定所有的進程申請資源必須以一定的順序(升序或降序)做操作來避免死結。
14、 Java中活鎖和死結有什麼區別?
這是上題的擴充,活鎖和死結類似,不同之處在於處於活鎖的線程或進程的狀態是不斷改變的,活鎖可以認為是一種特殊的饑餓。一個現實的活鎖例子是兩個人在狹小的走廊碰到,兩個人都試著避讓對方好讓彼此通過,但是因為避讓的方向都一樣導致最後誰都不能通過走廊。簡單的說就是,活鎖和死結的主要區別是前者進程的狀態可以改變但是卻不能繼續執行。
15、怎麼檢測一個線程是否擁有鎖?
在java.lang.Thread中有一個方法叫holdsLock(),若且唯若當前線程擁有某個具體對象的鎖它返回true。
16、有三個線程T1,T2,T3,怎麼確保它們按順序執行?
在多線程中有多種方法讓線程按特定順序執行,你可以用線程類的join()方法在一個線程中啟動另一個線程,另外一個線程完成該線程繼續執行。為了確保三個線程的順序你應該先啟動最後一個(T3調用T2,T2調用T1),這樣T1就會先完成而T3最後完成。
17、 Java線程池中submit() 和 execute()方法有什麼區別?
兩個方法都可以向線程池提交任務,execute()方法的傳回型別是void,它定義在Executor介面中, 而submit()方法可以返回持有計算結果的Future對象,它定義在ExecutorService介面中,它擴充了Executor介面,其它線程池類像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有這些方法。
18、什麼是阻塞式方法?
阻塞式方法是指程式會一直等待該方法完成期間不做其他事情,ServerSocket的accept()方法就是一直等待用戶端串連。這裡的阻塞是指調用結果返回之前,當前線程會被掛起,直到得到結果之後才會返回。此外,還有非同步和非阻塞式方法在任務完成前就返回。
19、多線程中的忙迴圈是什麼?
忙迴圈就是程式員用迴圈讓一個線程等待,不像傳統方法wait(), sleep() 或 yield() 它們都放棄了CPU控制,而忙迴圈不會放棄CPU,它就是在運行一個空迴圈。這麼做的目的是為了保留CPU緩衝,在多核系統中,一個等待線程醒來的時候可能會在另一個核心運行,這樣會重建緩衝。為了避免重建緩衝和減少等待重建的時間就可以使用它了。
20、如果同步塊內的線程拋出異常會發生什嗎?
無論你的同步塊是正常還是異常退出的,裡面的線程都會釋放鎖,所以對比鎖介面我更喜歡同步塊,因為它不用我花費精力去釋放鎖,
該功能可以在finally block裡釋放鎖實現。
21、Java多線程中調用wait() 和 sleep()方法有什麼不同?
Java程式中wait 和 sleep都會造成某種形式的暫停,它們可以滿足不同的需要。
wait()方法用於線程間通訊,如果等待條件為真且其它線程被喚醒時它會釋放鎖,而sleep()方法僅僅釋放CPU資源或者讓當前線程停止執行一段時間,
但不會釋放鎖。
22、資料庫的最佳化
1、硬體最佳化,提高機器效能,增加硬體等;
2、最佳化查詢語句,將限定性強的where條件放前,用exists代替in操作等;
3、最佳化索引,建立有效索引並檢查和修複缺少的統計資訊等
4、資料庫系統檔案最佳化,將資料檔案、索引檔案、記錄檔放置在不同的磁碟上,提高並行度等
5、大資料分割,當一個表的資料規模達到數億條時,索引已基本發揮不了作用:建立索引要花費大量時間,查詢時由於要掃描大的索引表也要花費大量時間。為了發揮索引的作用,可以將大表按照某個欄位拆分為若干個小表。
23、抽象類別(abstract class)和介面(interface)有什麼異同?
答:抽象類別和介面都不能夠執行個體化,但可以定義抽象類別和介面類型的引用。一個類如果繼承了某個抽象類別或者實現了某個介面都需要對其中的抽象方法全部進行實現,否則該類仍然需要被聲明為抽象類別。介面比抽象類別更加抽象,因為抽象類別中可以定義構造器,可以有抽象方法和具體方法,而介面中不能定義構造器而且其中的方法全部都是抽象方法。抽象類別中的成員可以是private、預設、protected、public的,而介面中的成員全都是public的。抽象類別中可以定義成員變數,而介面中定義的成員變數實際上都是常量。有抽象方法的類必須被聲明為抽象類別,而抽象類別未必要有抽象方法
24、闡述final、finally、finalize的區別。
答:
- final:修飾符(關鍵字)有三種用法:如果一個類被聲明為final,意味著它不能再派生出新的子類,即不能被繼承,因此它和abstract是反義詞。將變數聲明為final,可以保證它們在使用中不被改變,被聲明為final的變數必須在聲明時給定初值,而在以後的引用中只能讀取不可修改。被聲明為final的方法也同樣只能使用,不能在子類中被重寫。
- finally:通常放在try…catch…的後面構造總是執行代碼塊,這就意味著程式無論正常執行還是發生異常,這裡的代碼只要JVM不關閉都能執行,可以將釋放外部資源的代碼寫在finally塊中。
- finalize:Object類中定義的方法,Java中允許使用finalize()方法在垃圾收集器將對象從記憶體中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在銷毀對象時調用的,通過重寫finalize()方法可以整理系統資源或者執行其他清理工作。
25、闡述ArrayList、Vector、LinkedList的儲存效能和特性。
答:ArrayList和Vector都是使用數組方式儲存資料,此數組元素數大於實際儲存的資料以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等記憶體操作,所以索引資料快而插入資料慢,Vector中的方法由於添加了synchronized修飾,因此Vector是安全執行緒的容器,但效能上較ArrayList差,因此已經是Java中的遺留容器。LinkedList使用雙向鏈表實現儲存(將記憶體中零散的記憶體單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式儲存方式與數組的連續儲存方式相比,記憶體的利用率更高),按序號索引資料需要進行前向或後向遍曆,但是插入資料時只需要記錄本項的前後項即可,所以插入速度較快。Vector屬於遺留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,但是由於ArrayList和LinkedListed都是非安全執行緒的,如果遇到多個線程操作同一個容器的情境,則可以通過工具類Collections中的synchronizedList方法將其轉換成安全執行緒的容器後再使用(這是對裝潢模式的應用,將已有對象傳入另一個類的構造器中建立新的對象來增強實現)。
26、List、Map、Set三個介面存取元素時,各有什麼特點?
答:List以特定索引來存取元素,可以有重複元素。Set不能存放重複元素(用對象的equals()方法來區分元素是否重複)。Map儲存索引值對(key-value pair)映射,映射關係可以是一對一或多對一。Set和Map容器都有基於雜湊儲存和排序樹的兩種實現版本,基於雜湊儲存的版本理論存取時間複雜度為O(1),而基於排序樹版本的實現在插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。
27、TreeMap和TreeSet在排序時如何比較元素?Collections工具類中的sort()方法如何比較元素?
答:TreeSet要求存放的對象所屬的類必須實現Comparable介面,該介面提供了比較元素的compareTo()方法,當插入元素時會回調該方法比較元素的大小。TreeMap要求存放的索引值對映射的鍵必須實現Comparable介面從而根據鍵對元素進行排序。Collections工具類的sort方法有兩種重載的形式,第一種要求傳入的待排序容器中存放的對象比較實現Comparable介面以實現元素的比較;第二種不強制性的要求容器中的元素必須可比較,但是要求傳入第二個參數,參數是Comparator介面的子類型(需要重寫compare方法實現元素的比較),相當於一個臨時定義的定序,其實就是通過介面注入比較元素大小的演算法,也是對回調模式的應用(Java中對函數式編程的支援)。
28、Java中如何?序列化,有什麼意義?
答:序列化就是一種用來處理物件流程的機制,所謂物件流程也就是將對象的內容進行流化。可以對流化後的對象進行讀寫操作,也可將流化後的對象傳輸於網路之間。序列化是為瞭解決物件流程讀寫操作時可能引發的問題(如果不進行序列化可能會存在資料亂序的問題)。
要實現序列化,需要讓一個類實現Serializable介面,該介面是一個標識性介面,標註該類對象是可被序列化的,然後使用一個輸出資料流來構造一個對象輸出資料流並通過writeObject(Object)方法就可以將實現對象寫出(即儲存其狀態);如果需要還原序列化則可以用一個輸入資料流建立對象輸入資料流,然後通過readObject方法從流中讀取對象。序列化除了能夠實現對象的持久化之外,還能夠用於對象的深度複製
29、簡述一下你瞭解的設計模式。
原廠模式:工廠類可以根據條件產生不同的子類執行個體,這些子類有一個公用的抽象父類並且實現了相同的方法,但是這些方法針對不同的資料進行了不同的操作(多態方法)。當得到子類的執行個體後,開發人員可以調用基類中的方法而不必考慮到底返回的是哪一個子類的執行個體。
- 代理模式:給一個對象提供一個代理對象,並由代理對象控制原對象的引用。實際開發中,按照使用目的的不同,代理可以分為:遠程代理、虛擬代理、保護代理、Cache代理、防火牆代理、同步化代理、智能引用代理。
30、JSP有哪些內建對象?作用分別是什嗎?
答:JSP有9個內建對象:
- request:封裝用戶端的請求,其中包含來自GET或POST請求的參數;
- response:封裝伺服器對用戶端的響應;
- pageContext:通過該對象可以擷取其他對象;
- session:封裝使用者會話的對象;
- application:封裝伺服器運行環境的對象;
- out:輸出伺服器響應的輸出資料流對象;
- config:Web應用的設定物件;
- page:JSP頁面本身(相當於Java程式中的this);
- exception:封裝頁面拋出異常的對象。
31、get和post請求的區別?
答:
①get請求用來從伺服器上獲得資源,而post是用來向伺服器提交資料;
②get將表單中資料按照name=value的形式,添加到action 所指向的URL 後面,並且兩者使用"?"串連,而各個變數之間使用"&"串連;post是將表單中的資料放在HTTP協議的要求標頭或訊息體中,傳遞到action所指向URL;
③get傳輸的資料要受到URL長度限制(1024位元組);而post可以傳輸大量的資料,上傳檔案通常要使用post方式;
④使用get時參數會顯示在地址欄上,如果這些資料不是敏感性資料,那麼可以使用get;對于敏感資料還是應用使用post;
⑤get使用MIME類型application/x-www-form-urlencoded的URL編碼(也叫百分比符號編碼)文本的格式傳遞參數,保證被傳送的參數由遵循規範的文本組成,例如一個空格的編碼是"%20"。
32、講解JSP中的四種範圍。
答:JSP中的四種範圍包括page、request、session和application,具體來說:
- page代表與一個頁面相關的對象和屬性。
- request代表與Web客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web組件;需要在頁面顯示的臨時資料可以置於此範圍。
- session代表與某個使用者與伺服器建立的一次會話相關的對象和屬性。跟某個使用者相關的資料應該放在使用者自己的session中。
- application代表與整個Web應用程式相關的對象和屬性,它實質上是跨越整個Web應用程式,包括多個頁面、請求和會話的一個全域範圍
33、Hibernate中Session的load和get方法的區別是什嗎?
答:主要有以下三項區別:
① 如果沒有找到合格記錄,get方法返回null,load方法拋出異常。
② get方法直接返回實體類對象,load方法返回實體類對象的代理。
③ 在Hibernate 3之前,get方法只在一級緩衝中進行資料尋找,如果沒有找到對應的資料則越過二級緩衝,直接發出SQL陳述式完成資料讀取;load方法則可以從二級緩衝中擷取資料;從Hibernate 3開始,get方法不再是對二級緩衝唯寫不讀,它也是可以訪問二級緩衝的。
34、Hibernate如何?分頁查詢?
答:通過Hibernate實現分頁查詢,開發人員只需要提供HQL語句(調用Session的createQuery()方法)或查詢條件(調用Session的createCriteria()方法)、設定查詢起始行數(調用Query或Criteria介面的setFirstResult()方法)和最大查詢行數(調用Query或Criteria介面的setMaxResults()方法),並調用Query或Criteria介面的list()方法,Hibernate會自動產生分頁查詢的SQL語句
35、解釋一下什麼叫AOP(面向切面編程)?
答:AOP(Aspect-Oriented Programming)指一種程式設計範型,該範型以一種稱為切面(aspect)的語言構造為基礎,切面是一種新的模組化機制,用來描述分散在對象、類或方法中的橫切關注點(crosscutting concern)
36、Spring MVC的工作原理是怎樣的?
答:Spring MVC的工作原理如所示:
① 用戶端的所有請求都交給前端控制器DispatcherServlet來處理,它會負責調用系統的其他模組來真正處理使用者的請求。
②DispatcherServlet收到請求後,將根據請求的資訊(包括URL、HTTP協議方法、要求標頭、請求參數、Cookie等)以及HandlerMapping的配置找到處理該請求的Handler(任何一個對象都可以作為請求的Handler)。
③在這個地方Spring會通過HandlerAdapter對該處理器進行封裝。
④ HandlerAdapter是一個適配器,它用統一的介面對各種Handler中的方法進行調用。
⑤ Handler完成對使用者請求的處理後,會返回一個ModelAndView對象給DispatcherServlet,ModelAndView顧名思義,包含了資料模型以及相應的視圖的資訊。
⑥ ModelAndView的視圖是邏輯視圖,DispatcherServlet還要藉助ViewResolver完成從邏輯視圖到真實視圖對象的解析工作。
⑦ 當得到真正的視圖對象後,DispatcherServlet會利用視圖對象對模型資料進行渲染。
⑧ 用戶端得到響應,可能是一個普通的HTML頁面,也可以是XML或JSON字串,還可以是一張圖片或者一個PDF檔案。
37、選擇使用Spring架構的原因(Spring架構為企業級開發帶來的好處有哪些)?
答:可以從以下幾個方面作答:
- 非侵入式:支援基於POJO的編程模式,不強制性的要求實現Spring架構中的介面或繼承Spring架構中的類。
- IoC容器:IoC容器輔助應用程式管理對象以及對象之間的依賴關係,對象之間的依賴關係如果發生了改變只需要修改設定檔而不是修改代碼,因為代碼的修改可能意味著項目的重新構建和完整的迴歸測試。有了IoC容器,程式員再也不需要自己編寫工廠、單例,這一點特別符合Spring的精神”不要重複的發明輪子”。
- AOP(面向切面編程):將所有的橫切關注功能封裝到切面(aspect)中,通過配置的方式將橫切關注功能動態添加到目標代碼上,進一步實現了商務邏輯和系統服務之間的分離。另一方面,有了AOP程式員可以省去很多自己寫代理類的工作。
- MVC:Spring的MVC架構是非常優秀的,從各個方面都可以甩Struts 2幾條街,為Web展示層提供了更好的解決方案。
- 交易管理:Spring以寬廣的胸懷接納多種持久層技術,並且為其提供了聲明式的交易管理,在不需要任何一行代碼的情況下就能夠完成交易管理。
- 其他:選擇Spring架構的原因還遠不止於此,Spring為Java企業級開發提供了一站式選擇,你可以在需要的時候使用它的部分和全部,更重要的是,你甚至可以在感覺不到Spring存在的情況下,在你的項目中使用Spring提供的各種優秀的功能。
38、闡述Spring架構中Bean的生命週期?
答:
① Spring IoC容器找到關於Bean的定義並執行個體化該Bean。
② Spring IoC容器對Bean進行依賴注入。
③ 如果Bean實現了BeanNameAware介面,則將該Bean的id傳給setBeanName方法。
④ 如果Bean實現了BeanFactoryAware介面,則將BeanFactory對象傳給setBeanFactory方法。
⑤ 如果Bean實現了BeanPostProcessor介面,則調用其postProcessBeforeInitialization方法。
⑥ 如果Bean實現了InitializingBean介面,則調用其afterPropertySet方法。
⑦ 如果有和Bean關聯的BeanPostProcessors對象,則這些對象的postProcessAfterInitialization方法被調用。
⑧ 當銷毀Bean執行個體時,如果Bean實現了DisposableBean介面,則調用其destroy方法。
162、依賴注入時如何注入集合屬性?
答:可以在定義Bean屬性時,通過<list> / <set> / <map> / <props>分別為其注入列表、集合、映射和索引值都是字串的映射屬性。
JAVA基礎面試題