【面試題】Java面試題--技術深度--個人學習記錄
1、有沒有看過JDK原始碼,看過的類實現原理是什麼。
2、HTTP協議
3、TCP協議
4、一致性Hash演算法
5、JVM如何載入位元組碼檔案
loading、verification、preparation 、 Resolution、initialization 、using 、unloading
6、類載入器如何解除安裝位元組碼(不是很清楚)
堆中的相應物件置為null,清空方法區中對應的二進位制資料結構及其他資料變數等。
7、IO和NIO的區別,NIO優點
同步非同步IO:同步非同步指的是 應用程式與作業系統OS之間的關係,同步需要等待作業系統切換到核心狀態進行IO,等待IO結束後,切換到使用者狀態,繼續執行 ;或者,使用者程式輪詢訪問IO。即同步IO需要參與到IO這個過程。而非同步是交給OS一個IO任務,IO完成後OS會通知應用程式。同異步體現在操作IO的主體,同步的主體是使用者執行緒需要執行最後的IO(包括輪詢),而非同步IO是作業系統執行最後的IO,使用者執行緒只需要獲取資料即可。
阻塞非阻塞IO:
同步非阻塞:NIO初版。引入buffer,同步即操作主體仍然為使用者執行緒,非阻塞即不會阻塞線上程,但是需要執行緒輪詢檢查IO狀態,buffer的迴圈讀取。
非同步非阻塞:NIO2.0,buffer和回撥,操作主體為核心,OS完成之後即回撥給使用者執行緒並通知。更不會阻塞執行緒。
傳統IO:面向流。即輸入輸出字元位元組流 InputStream、Reader。之後加上了buffer緩衝。總之是字元位元組流的所有擴充套件API。
NIO:面向塊。同步非阻塞IO。引入channel和buffer,檔案輸入流獲取channel→讀入buffer→buffer寫入channel→channel寫入檔案。
NIO優點:1、網路NIO無阻塞(很重要) 2、引入buffer,能夠減少檔案操作次數 3、面向塊,操作速度比傳統IO快。
示例:
public static void copyFileUseNIO(String src,String dst) throws IOException {
//宣告原始檔和目標檔案
FileInputStream fi = new FileInputStream(new File(src));
FileOutputStream fo = new FileOutputStream(new File(dst));
//獲得傳輸通道channel
FileChannel inChannel = fi.getChannel();
FileChannel outChannel = fo.getChannel();
//獲得容器buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
//判斷是否讀完檔案
int eof = inChannel.read(buffer);
if (eof == -1) {
break;
}
//重設一下buffer的position=0,limit=position
buffer.flip();
//開始寫
outChannel.write(buffer);
//寫完要重置buffer,重設position=0,limit=capacity
buffer.clear();
}
inChannel.close();
outChannel.close();
fi.close();
fo.close();
}
關於NIO的網路程式設計:此處體現了非阻塞的IO。
流程簡述:有些類似於 severSocket 與 Socket 程式設計。
伺服器端:ServerSocketChannel監聽埠,並多開幾個channel,同時將channel註冊到selector元件裡面,並給selector設定channel發來的感興趣事件(此處是client與server都會設定的東西,4種值),設定好事件後,需要對channel進行迴圈監聽,並且判斷client過來的事件屬性,做出channel資料接收。
客戶端:SocketChannle,初始化hostname與port,將輸入輸入封裝為byte[] → byte陣列put進入byteBuffer → bufferBuffer寫入channel。
8、Java執行緒池的實現原理,keepAliveTime等引數的作用。
執行緒池,對提交上的執行緒進行統一的管理。使用者建立執行緒但是由執行緒池來管理執行,以及所有執行緒的執行順序、生命週期等,都是由執行緒池管理,使用者不再需要關心執行緒池何時清除。執行緒池
4個建構函式,引數分別是下面引數的部分組合。
執行緒池執行流程是:提交執行緒 → 核心執行緒是否滿?繼續:建立 → 等待對列是否滿?繼續 : 入隊 → 是否超出最大執行緒數?異常處理handler : 繼續 → 非核心是否滿?建立 圖
- corePoolSize:核心池的大小,這個引數跟後面講述的執行緒池的實現原理有非常大的關係。在建立了執行緒池後,預設情況下,執行緒池中並沒有任何執行緒,而是等待有任務到來才建立執行緒去執行任務,除非呼叫了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出,是預建立執行緒的意思,即在沒有任務到來之前就建立corePoolSize個執行緒或者一個執行緒。預設情況下,在建立了執行緒池後,執行緒池中的執行緒數為0,當有任務來之後,就會建立一個執行緒去執行任務,當執行緒池中的執行緒數目達到corePoolSize後,就會把到達的任務放到快取隊列當中;
- maximumPoolSize:執行緒池最大執行緒數,這個引數也是一個非常重要的引數,它表示線上程池中最多能建立多少個執行緒;
- keepAliveTime:表示執行緒沒有任務執行時最多保持多久時間會終止。預設情況下,只有當執行緒池中的執行緒數大於corePoolSize時,keepAliveTime才會起作用,直到執行緒池中的執行緒數不大於corePoolSize,即當執行緒池中的執行緒數大於corePoolSize時,如果一個執行緒空閒的時間達到keepAliveTime,則會終止,直到執行緒池中的執行緒數不超過corePoolSize。但是如果呼叫了allowCoreThreadTimeOut(boolean)方法,線上程池中的執行緒數不大於corePoolSize時,keepAliveTime引數也會起作用,直到執行緒池中的執行緒數為0;
- unit:引數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:
TimeUnit.DAYS; //天 TimeUnit.HOURS; //小時 TimeUnit.MINUTES; //分鐘 TimeUnit.SECONDS; //秒 TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙 TimeUnit.NANOSECONDS; //納秒
- workQueue:一個阻塞佇列,用來儲存等待執行的任務,這個引數的選擇也很重要,會對執行緒池的執行過程產生重大影響,一般來說,這裡的阻塞佇列有以下幾種選擇:
ArrayBlockingQueue; LinkedBlockingQueue; SynchronousQueue;
ArrayBlockingQueue和PriorityBlockingQueue使用較少,一般使用LinkedBlockingQueue和Synchronous。執行緒池的排隊策略與BlockingQueue有關。
- threadFactory:執行緒工廠,主要用來建立執行緒;
- handler:表示當拒絕處理任務時的策略,有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務並丟擲RejectedExecutionException異常。 ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不丟擲異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄佇列最前面的任務,然後重新嘗試執行任務(重複此過程) ThreadPoolExecutor.CallerRunsPolicy:由呼叫執行緒處理該任務
具體引數的配置與執行緒池的關係將在下一節講述。
而官方不推薦這種方法,而是給出了Executors中的4個靜態建立執行緒池方法,已經定義好部分引數。
CachedThreadPool:可快取的執行緒池,該執行緒池中沒有核心執行緒,非核心執行緒的數量為Integer.max_value,就是無限大,當有需要時建立執行緒來執行任務,沒有需要時回收執行緒,適用於耗時少,任務量大的情況。同步排隊策略
SecudleThreadPool:週期性執行任務的執行緒池,按照某種特定的計劃執行執行緒中的任務,有核心執行緒,但也有非核心執行緒,非核心執行緒的大小也為無限大。適用於執行週期性的任務。特定的一種延遲排隊策略
SingleThreadPool:只有一條執行緒來執行任務,適用於有順序的任務的應用場景。linked排隊策略
FixedThreadPool:定長的執行緒池,有核心執行緒,核心執行緒的即為最大的執行緒數量,沒有非核心執行緒。linked排隊策略
針對排隊策略的深層探討:
ArrayBlockingQueue:陣列形式的,有界排隊策略,可以避記憶體被耗光。AQS 抽象排隊同步器
LinkedBlockingQueue:連結串列形式的排隊策略,無界。AQS
SynchronousQueue:同步的,佇列中只能存一個,且這個必須被取走後下一個才能進入。 CAS 比較並交換
AQS 與 CAS(????????):AQS CAS AQS
AQS 即抽象排隊同步器,可重入 reenstrantLock 也是根據內部實現一個自定義同步器來實現的,同步器又分為了 獨佔鎖 和 共享模式,自定義同步器只需要重寫部分方法即可。 並且其中還有 公平 與 非公平的策略提高併發量。
CAS 即比較並交換,現有的值 A 與期待值 B 不一樣,則將現有值 A 賦值為 C,否則不操作,不斷的迴圈請求,並且現有值 A 是通過 volatile 關鍵字修飾的,可以保證每次get的 A 是最新的值,這樣就可以確保執行的執行緒是一個有序的執行緒序列,實現了不加鎖的同步方式。因為CAS是基於樂觀鎖的,也就是說當寫入的時候,如果暫存器舊值已經不等於現值,說明有其他CPU在修改,那就繼續嘗試。所以這就保證了操作的原子性。其中有ABA的缺點,即經過幾次修改變回之前的值A,而被阻塞的執行緒只會判斷值,所以引入版本判別,記錄更改記錄。使用volatile(省掉鎖,卻不能原子性,因為一次賦值操作分為了三步,copy到本地→賦值→重新整理到快取),而Atomic(volatile+CAS),同時起作用實現鎖。關於 volatile 非原子性
參考:
https://www.cnblogs.com/xzn-smy/p/9172555.html
https://blog.csdn.net/wbb_1216/article/details/62882921
http://m.blog.sina.com.cn/s/blog_ee34aa660102wsuv.html#page=7
9、HTTP連線池實現原理
主要是用來降低 連線次數,因為每次請求都經過三次握手、四次釋放,網路延遲很大。(具體使用方法及原理?????等計算機網路學完部分)
10、資料庫連線池實現原理
建立一個管理機制,對connection、statement、result三種資源進行統一的管理,即開有限次資源的介面,交給一個數據結構進行統一的管理,然後釋放執行緒對這個介面的使用權,通過併發控制來決定執行緒擁有公有訪問介面的權利及順序。很類似與執行緒池。https://www.cnblogs.com/newpanderking/p/3875749.html
11、資料庫的實現原理
參考:
http://blog.jobbole.com/100349/
資料庫實現原理: