一、JDK和JRE區別?java
JDK是整個JAVA的核心,包括了Java運行環境JRE,一堆Java工具和Java基礎的類庫。
經過JDK開發人員將源碼文件(java文件)編譯成字節碼文件(class文 件)。
JRE是Java運行環境,不含開發環境,即沒有編譯器和調試器。將class文件加載到內存準備運行。
二、final關鍵字,抽象類可使用final修飾嗎? 數據庫
1.用來修飾數據,包括成員變量和局部變量,該變量只能被賦值一次且它的 值沒法被改變。對於成員變量來說,必須在聲明時或者構造方法中對它賦值;
2.修飾方法,表示該方法沒法被重寫;
3.修飾類,表示該類沒法被繼承。
注:抽象類是被用於繼承的,final修飾表明不可修改、不可繼承的。因此不能用final修飾抽象類。
三、JAVA容器數組
(1)ArrayList底層數組實現,封裝了常見的增刪改查操做,而且支持動態擴容。適合查找多的場合。
(2)LinkedList基於鏈表實現的列表。適合增刪狀況較多的場合。
(3)TreeSet,基於二叉排序樹(紅黑樹)實現的。TreeSet裏最典型的就是它用到了兩種排序方式,即基於元素對象自身的實現的Comparable接口的天然排序,以及基於更爲靈活不與單個元素綁定的Comparator接口的客戶化排序。本身在構造的時候傳入一個比較器便可。
(4)HashMap是用來存儲鍵值對的映射關係,底層是用數組+鏈表實現的。結合put操做講一下。
(5)HashSet其實就是基於HashMap實現的,只不過將值固定爲一個固定的值。
(6)LinkedHashMap,支持按照插入順序排序。
(7)PriorityQueue優先級隊列,一個基於優先級堆的無界優先級隊列
四、多線程安全在三個方面體現:緩存
1.原子性:提供互斥訪問,同一時刻只能有一個線程對數據進行操做;
2.可見性:一個線程對主內存的修改能夠及時地被其餘線程看到;
3.有序性:程序執行的順序按照代碼的前後順序執行,因爲指令重排序,結果通常雜亂無序。
五、JAVA怎麼保證線程安全?安全
(1)保證原子性
經常使用的保證Java操做原子性的工具是鎖和同步方法(或者同步代碼塊)。
使用鎖,能夠保證同一時間只有一個線程能拿到鎖,也就保證了同一時間只有一個線程能執行申請鎖和釋放鎖之間的代碼。
與鎖相似的是同步方法或者同步代碼塊。
使用非靜態同步方法時,鎖住的是當前實例;使用靜態同步方法時,鎖住的是該類的Class對象;使用靜態代碼塊時,鎖住的是synchronized關鍵字後面括號內的對象。
不管使用鎖仍是synchronized,本質都是同樣,經過鎖來實現資源的排性,從而實際目標代碼段同一時間只會被一個線程執行,進而保證了目標代碼段的原子性。這是一種以犧牲性能爲代價的方法。
(2)保證可見性
Java提供了volatile關鍵字來保證可見性。
因爲JMM是基於共享內存實現線程通訊的,因此會存在緩存一致性的問題。
當使用volatile修飾某個變量時,它會保證對該變量的修改會當即被更新到內存中,而且將其它緩存中對該變量的緩存設置成無效。
所以其它線程須要讀取該值時必須從主內存中讀取,從而獲得最新的值。
(3)保證順序性
編譯器和處理器對指令進行從新排序時,會保證從新排序後的執行結果和代碼順序執行的結果一致,因此從新排序過程並不會影響單線程程序的執行,卻可能影響多線程程序併發執行的正確性。
Java中可經過volatile在必定程序上保證順序性,另外還能夠經過synchronized和鎖來保證順序性。
synchronized和鎖保證順序性的原理和保證原子性同樣,都是經過保證同一時間只會有一個線程執行目標代碼段來實現的。
除了從應用層面保證目標代碼段執行的順序性外,JVM還經過被稱爲happens-before原則隱式地保證順序性。
兩個操做的執行順序只要能夠經過happens-before推導出來,則JVM會保證其順序性,反之JVM對其順序性不做任何保證,可對其進行任意必要的從新排序以獲取高效率。
六、有沒有其餘方法保證線程安全?數據結構
有。儘量避免引發非線程安全的條件——共享變量。
若是能從設計上避免共享變量的使用,便可避免非線程安全的發生,也就無須經過鎖或者synchronized以及volatile解決原子性、可見性和順序性的問題。
還有不可變對象可使用final修飾的對象保證線程安全,因爲final修飾的引用型變量(除String外)不可變是指引用不可變,但其指向的對象是可變的,因此此類必須安全發佈,即不能對外提供能夠修改final對象的接口。
七、JAVA怎麼避免死鎖?多線程
一、加鎖順序
當多個線程須要相同的一些鎖,可是按照不一樣的順序加鎖,死鎖就很容易發生。若是能確保全部的線程都是按照相同的順序得到鎖,那麼死鎖就不會發生。
二、加鎖時限
在嘗試獲取鎖的時候加一個超時時間,這也就意味着在 嘗試獲取鎖的過程當中若超過了這個時限該線程則放棄對該鎖請求。若一個線程沒有在給定的時限內成功得到全部須要的鎖,則會進行回退並釋放全部已經得到的鎖,而後等待一段隨機的時間再重試。這段隨機的等待時間讓其它線程有機會嘗試獲取相同的這些鎖,而且讓該應用在沒有得到鎖的時候能夠繼續運行。
三、死鎖檢測
死鎖檢測是一個更好的死鎖預防機制,它主要是針對那些不可能實現按序加鎖而且鎖超時也不可行的場景。每當一個線程得到了鎖,會在線程和鎖相關的數據結構中(map、graph等等)將其記下。
除此以外,每當有線程請求鎖,也須要記錄在這個數據結構中。當一個線程請求鎖失敗時,這個線程能夠遍歷鎖的關係圖看看是否有死鎖發生。
那麼當檢測出死鎖時,這些線程該作些什麼呢?一個可行的作法是釋放全部鎖,回退,而且等待一段隨機的時間後重試。
這個和簡單的加鎖超時相似,不同的是隻有死鎖已經發生了纔回退,而不會是由於加鎖的請求超時了。
雖然有回退和等待,可是若是有大量的線程競爭同一批鎖,它們仍是會重複地死鎖。一個更好的方案是給這些線程設置優先級,讓一個(或幾個)線程回退,剩下的線程就像沒發生死鎖同樣繼續保持着它們須要的鎖。若是賦予這些線程的優先級是固定不變的,同 一批線程老是會擁有更高的優先級。爲避免這個問題,能夠在死鎖發生的時候設置隨機的優先級。
八、數據庫爲何創建索引?併發
優勢:
第一,經過建立惟一性索引,能夠保證數據庫表中每一行數據的惟一性。
第二,能夠大大加快數據的檢索速度,這也是建立索引的最主要的緣由。
第三,能夠加速表和表之間的鏈接,特別是在實現數據的參考完整性方面特別有意義。
第四,在使用分組和排序子句進行數據檢索時,一樣能夠顯著減小查詢中分組和排序的時間。
第五,經過使用索引,能夠在查詢的過程當中,使用優化隱藏器,提升系統的性能。
缺點:
第一,建立索引和維護索引要耗費時間,這種時間隨着數據量的增長而增長。
第二,索引須要佔物理空間,除了數據表佔數據空間以外,每個索引還要佔必定的物理空間,若是要創建聚簇索引,那麼須要的空間就會更大。
第三,當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,這樣就下降了數據的維護速度。
適合應用索引的:常常須要搜索的列上,常常須要範圍查詢的,主鍵等。
不適合引用索引的:常常不用來查詢的,大字段的好比text段等。
九、硬盤裏一個50G大小的文件和另外一個100G文件,裏面存儲着不一樣的名字,如何在一個內存很小的電腦上實現兩個文件的交集運算。app
方法一:先用哈希切分,再用分桶+組內Hash索引的方法
將一個大文件裏的數據使用一個哈希函數進行切分爲許多小的文件,這樣相同的數據必定會進入同一個文件當中去,並進行文件編號。對另一個文件也是用相同的哈希函數進行切分爲相同數目的小文件,這樣咱們只須要將相同編號裏的文件進行比較。這樣其時間複雜度就會下降爲 O(n)。相同的文件查找時能夠先對一個文件創建hash索引(桶+鏈表),而後對另外一個文件依次按照索引進行查找。若hash值相同在進行進一步比較便可。
方法二:位圖方法 O(n)
這有個前提是文件中必須存儲的是數字。那麼根據位圖,咱們能夠將第一個文件中全部數據映射到位圖中去。而後再不斷導入第二個文件,若是發現某個數字已經存儲在位圖中,就說明這是兩個文件的交集。
方法三:近似解-布隆過濾器 O(n)
將A文件每一個數據通過多個Hash函數映射到一個位圖上,而後第二個文件同 樣的作法,若是所有命中,說明相同。不然說明不存在。可是這個有必定的錯誤率。
方法四:多路歸併排序 Onlog(n)+O(n)
先將文件劃分爲不少等量的小文件。而後對每一個小文件導入內存進行內部排 序。這樣就有了不少有序的小文件。而後對不少有序的小文件進行多路歸併排序,而後不斷寫入大文件便可。(Onlog(n))最終就獲得了一個有序的大文件。最後對兩個有序的大文件進行查找相同的值便可(O(n))。