歡迎光臨
每天分享高質量文章

Java中高階面試題(4)

點選上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

 

這裡選了幾道高頻面試題以及一些解答。不一定全部正確,有一些是沒有固定答案的,如果發現有錯誤的歡迎糾正,如果有更好的回答,熱烈歡迎留言探討。


BIO、NIO和AIO的區別


Java BIO : 同步並阻塞,伺服器實現樣式為一個連線一個執行緒,即客戶端有連線請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不做任何事情會造成不必要的執行緒開銷,當然可以透過執行緒池機制改善。


Java NIO : 同步非阻塞,伺服器實現樣式為一個請求一個執行緒,即客戶端傳送的連線請求都會註冊到多路復用器上,多路復用器輪詢到連線有I/O請求時才啟動一個執行緒進行處理。


Java AIO: 非同步非阻塞,伺服器實現樣式為一個有效請求一個執行緒,客戶端的I/O請求都是由OS先完成了再通知伺服器應用去啟動執行緒進行處理。


NIO比BIO的改善之處是把一些無效的連線擋在了啟動執行緒之前,減少了這部分資源的浪費(因為我們都知道每建立一個執行緒,就要為這個執行緒分配一定的記憶體空間)


AIO比NIO的進一步改善之處是將一些暫時可能無效的請求擋在了啟動執行緒之前,比如在NIO的處理方式中,當一個請求來的話,開啟執行緒進行處理,但這個請求所需要的資源還沒有就緒,此時必須等待後端的應用資源,這時執行緒就被阻塞了。


適用場景分析:

 BIO方式適用於連線數目比較小且固定的架構,這種方式對伺服器資源要求比較高,併發侷限於應用中,JDK1.4以前的唯一選擇,但程式直觀簡單易理解,如之前在Apache中使用。


 NIO方式適用於連線數目多且連線比較短(輕操作)的架構,比如聊天伺服器,併發侷限於應用中,程式設計比較複雜,JDK1.4開始支援,如在 Nginx,Netty中使用。


 AIO方式使用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫OS參與併發操作,程式設計比較複雜,JDK7開始支援,在成長中,Netty曾經使用過,後來放棄。


類似參考文章,請移駕:

Java中BIO,NIO,AIO的理解


java中常說的堆和棧,分別是什麼資料結構;另外,為什麼要分為堆和棧來儲存資料


棧是一種具有後進先出性質的資料結構,也就是說後存放的先取,先存放的後取。

堆是一種經過排序的樹形資料結構,每個結點都有一個值。通常我們所說的堆的資料結構,是指二叉堆。堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。由於堆的這個特性,常用來實現優先佇列,堆的存取是隨意的。

為什麼要劃分堆和棧

1、從軟體設計的角度看,棧代表了處理邏輯,而堆代表了資料。這樣分開,使得處理邏輯更為清晰。

2、堆與棧的分離,使得堆中的內容可以被多個棧共享。一方面這種共享提供了一種有效的資料互動方式(如:共享記憶體),另一方面,堆中的共享常量和快取可以被所有棧訪問,節省了空間。

3、棧因為執行時的需要,比如儲存系統執行的背景關係,需要進行地址段的劃分。由於棧只能向上增長,因此就會限制住棧儲存內容的能力。而堆不同,堆中的物件是可以根據需要動態增長的,因此棧和堆的拆分,使得動態增長成為可能,相應棧中只需記錄堆中的一個地址即可。

4、體現了Java面向物件這一核心特點(也可以繼續說一些自己的理解)

類似參考文章,請移駕:

Java中堆記憶體和棧記憶體詳解


為什麼要用執行緒池


那先要明白什麼是執行緒池

執行緒池是指在初始化一個多執行緒應用程式過程中建立一個執行緒集合,然後在需要執行新的任務時重用這些執行緒而不是新建一個執行緒。

使用執行緒池的好處

1、執行緒池改進了一個應用程式的響應時間。由於執行緒池中的執行緒已經準備好且等待被分配任務,應用程式可以直接拿來使用而不用新建一個執行緒。

2、執行緒池節省了CLR 為每個短生存週期任務建立一個完整的執行緒的開銷並可以在任務完成後回收資源。

3、執行緒池根據當前在系統中執行的行程來最佳化執行緒時間片。

4、執行緒池允許我們開啟多個任務而不用為每個執行緒設定屬性。

5、執行緒池允許我們為正在執行的任務的程式引數傳遞一個包含狀態資訊的物件取用。

6、執行緒池可以用來解決處理一個特定請求最大執行緒數量限制問題。

類似參考文章,請移駕:

JAVA執行緒池原理詳解(1)

JAVA執行緒池原理詳解(2)

Java多執行緒和執行緒池


msyql最佳化經驗

1、對查詢進行最佳化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

2、應儘量避免在 where 子句中使用!=或<>運運算元,否則引擎將放棄使用索引而進行全表掃描。

3、儘量使用數字型欄位,若只含數值資訊的欄位儘量不要設計為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連線時會逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。

4、任何地方都不要使用 select * from t ,用具體的欄位串列代替“*”,不要傳回用不到的任何欄位。

5、避免頻繁建立和刪除臨時表,以減少系統表資源的消耗。諸如此類,等等等等……

類似參考文章,請移駕:

關鍵的十個MySQL效能最佳化技巧

MySQL索引最佳化


悲觀鎖和樂觀鎖的區別,怎麼實現

悲觀鎖:一段執行邏輯加上悲觀鎖,不同執行緒同時執行時,只能有一個執行緒執行,其他的執行緒在入口處等待,直到鎖被釋放。

樂觀鎖:一段執行邏輯加上樂觀鎖,不同執行緒同時執行時,可以同時進入執行,在最後更新資料的時候要檢查這些資料是否被其他執行緒修改了(版本和執行初是否相同),沒有修改則進行更新,否則放棄本次操作。


悲觀鎖的實現:

//0.開始事務
begin;/begin work;/start transaction; (三者選一就可以)
//1.查詢出商品資訊
select status from t_goods where id=1 for update;
//2.根據商品資訊生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status為2
update t_goods set status=2;
//4.提交事務
commit;/commit work;

樂觀鎖的實現

1.查詢出商品資訊
select (status,status,versionfrom t_goods where id=#{id}
2.根據商品資訊生成訂單
3.修改商品status2
update t_goods 
set status=2,version=version+1
where id=#{idand version=#{version};

類似參考文章,請移駕:

Java高併發解決方案(參考文)


贊(0)

分享創造快樂