在3月1號投完簡歷,做好測評以後,我是一直等啊等,始終期待著一面的到來。
好不容易在3月8號這天中午12點10左右接到了來自阿里的面試電話。
剛開始,我是一臉的懵逼啊,面試官問我:“你是不是面過了???”我是一臉黑臉問號.jpg。Excuse me?在我一番解釋後,終於進入了正題。
首先還是自我介紹。然後下面是問題清單:
1、平時在專案中主要負責哪塊技術啊?(我回答資料庫方面的程式碼)好,那麼請問,你所知道的資料庫方面所需要注意的地方有什麼?怎麼優化資料庫?
引申出來以後,他又我問了我關於left join與right join的區別,(我回答了出來),然後,他又問我那inner join呢?(我當時是忘記了,一臉懵逼啊,絕望放棄回答)?用很多join好嗎,有什麼 缺點?(效率降低)
關於索引:
應該建索引的欄位:
1.經常作為查詢條件的欄位
2.外來鍵
3.經常需要排序的欄位
4.分組排序的欄位應該少建或者不建索引的欄位有:
1.表記錄太少
2.經常需要插入,刪除,修改的表,
3.表中資料重複且分佈平均的欄位
2、HTTP的特點,TCP/UDP特點以及區別?
1.支援客戶/伺服器模式。
2.簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯絡的型別不同。由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。
3.靈活:HTTP允許傳輸任意型別的資料物件。正在傳輸的型別由Content-Type加以標記。
4.無連線:無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。
5.無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。
3、HashMap、HashTable、ConCurrentHasgMap的區別以及實現原理?
ConCurrentHasgMap呼叫get()方法的時候有鎖嗎?
對於put和remove操作,是使用鎖同步來進行的,不過是用的ReentrantLock而不是synchronized,效能上要更高一些。它們的實現前文都已經提到過,就沒什麼可分析的了。
我們還需要知道一點,ConcurrentHashMap的迭代器不是Fast-Fail的方式,所以在迭代的過程中別其他執行緒新增/刪除了元素,不會丟擲異常,也不能體現出元素的改動。但也沒有關係,因為每個entry的成員除了value都是final修飾的,暴漏出去也不會對其他元素造成影響。
- 為什麼hashmap擴容是是擴大成原來的2倍,而不是3倍?
友情連結:深入理解HashMap(及hash函式的真正巧妙之處)
4、怎麼實現併發程式設計?請詳細描述?
鎖機制(Lock)、CAS無鎖演算法、Synchronized區別
5、類載入機制(如果自己寫幾個Jar包,應該放哪裡?)
6、String、StringBuffer、StringBuilder的區別?
如果StringBuilder後增加一個字串常量,並且這時候是多執行緒執行,那這時候StringBuilder是執行緒安全的嗎?
字串常量就是不能改變該物件,而後者是可是改變的字串物件,他不像String一樣,需要每次建立,後兩者是在原有的字串物件進行操作的。
7、JDK7、8的區別?
在JMM方面的區別:
永久代
在JDK8之前的HotSpot實現中,類的後設資料如方法資料、方法資訊(位元組碼,棧和變數大小)、執行時常量池、已確定的符號引用和虛方法表等被儲存在永久代中,32位預設永久代的大小為64M,64位預設為85M,可以通過引數-XX:MaxPermSize進行設定,一旦類的後設資料超過了永久代大小,就會丟擲OOM異常。
虛擬機器團隊在JDK8的HotSpot中,把永久代從Java堆中移除了,並把類的後設資料直接儲存在本地記憶體區域(堆外記憶體),稱之為元空間。
這樣做有什麼好處?
有經驗的同學會發現,對永久代的調優過程非常困難,永久代的大小很難確定,其中涉及到太多因素,如類的總數、常量池大小和方法數量等,而且永久代的資料可能會隨著每一次Full GC而發生移動。
而在JDK8中,類的後設資料儲存在本地記憶體中,元空間的最大可分配空間就是系統可用記憶體空間,可以避免永久代的記憶體溢位問題,不過需要監控記憶體的消耗情況,一旦發生記憶體洩漏,會佔用大量的本地記憶體。
ps:JDK7之前的HotSpot,字串常量池的字串被儲存在永久代中,因此可能導致一系列的效能問題和記憶體溢位錯誤。在JDK8中,字串常量池中只儲存字串的引用。
8、JMM在初始化堆記憶體時,新生代與老年代的預設比例是多少?
永久代不屬於堆記憶體,堆記憶體只包含新生代和老年代。
預設的,新生代 ( Young ) 與老年代 ( Old ) 的比例的值為 1:2 ( 該值可以通過引數 –XX:NewRatio 來指定 ),即:新生代 ( Young ) = 1/3 的堆空間大小。
老年代 ( Old ) = 2/3 的堆空間大小。其中,新生代 ( Young ) 被細分為 Eden 和 兩個 Survivor 區域,這兩個 Survivor 區域分別被命名為 from 和 to,以示區分。
預設的,Edem : from : to = 8 : 1 : 1 ( 可以通過引數 –XX:SurvivorRatio 來設定 ),即: Eden = 8/10 的新生代空間大小,from = to = 1/10 的新生代空間大小。
JVM 每次只會使用 Eden 和其中的一塊 Survivor 區域來為物件服務,所以無論什麼時候,總是有一塊 Survivor 區域是空閒著的。
因此,新生代實際可用的記憶體空間為 9/10 ( 即90% )的新生代空間。
- Java記憶體模型的描述?
9、Spring中控制反轉定義?相比於建立物件的好處?AOP程式設計的優點?
友情連結:三大框架的原理及優缺點
原來我們的程式我們控制的是具體的實現,寫程式直接寫實現,現在我們控制的是它的介面它的抽象,原來我們依賴的是它的實現,現在我們依賴的是它的抽象。從具體的實現反轉到抽象的概念上,我們針對的是介面程式設計。
1)降低元件之間的耦合度,實現軟體各層之間的解耦。
Controller——>Service——>DAO
2)可以使用容器提供的眾多服務,如:事務管理服務、訊息服務等等。當我們使用容器管理事務時,開發人員就不再需要手工控制事務.也不需處理複雜的事務傳播。
3)容器提供單例模式支援,開發人員不再需要自己編寫實現程式碼。
4)容器提供了AOP技術,利用它很容易實現如許可權攔截、執行期監控等功能。
5)容器提供的眾多輔作類,使用這些類能夠加快應用的開發,如: JdbcTemplate、 HibernateTemplate。
6)Spring對於主流的應用框架提供了整合支援,如:整合Hibernate、JPA、Struts等,這樣更便於應用的開發。
7) 使用spring容器可以提供的服務:事務管理服務,JMS服務,Spring Core核心服務,持久化服務等。
8)如果使用Spring, 我們就不再需要手工控制事務,例如在Hibernate中控制事務的語句 session.beginTransaction();session.getTransaction().commit();
9)使用Spring,不再需要我們處理複雜的事務傳播行為。
10、SpringMVC中動態代理的實現機制,原始碼?
友情連結:Spring AOP動態代理原理與實現方式 (轉)
友情連結:Java中動態代理實現機制
11、讀過哪些原始碼,請詳細描述一個你最熟悉的?(我回答ArrayList)
12、JVM虛擬機器?請詳細描述?
13、Java GC回收機制?請詳細描述?
14、問了兩道智力題!!!!!
(1)有8個產品,其中有一個次品(有可能偏重,有可能偏輕),那麼如何用天平秤三次找出那個次品?
(2)忘記了。。。。關於買賣問題
15、看過GitHub上的開放原始碼嗎(比如阿里,騰訊優秀團隊的)?
16、使用過哪些程式碼管理工具?(Git,Maven)熟練使用嗎?會不會使用GitHub上傳程式碼?
17、使用過哪些寫程式碼的工具?(Myeclipse和IDE),列出你常用的快捷鍵?
18、學習程式設計的方法、渠道?(看部落格,網站)?上哪些網站?
19、說說自己的優缺點?學習時間的分配?
20、漏了一個問題,怎麼實現讓兩個執行緒交替執行?(用程式碼實現?)
一般來說執行緒鎖可以用:Synchronized、Lock。
這個題目的難點不在於同步塊,而在於怎麼樣設計這個兩個執行緒的交替實現。由於執行緒爭用cpu的隨機性,就需要A線,B執行緒執行,在B執行完一次進入等待之前喚醒A,如此往復,那麼這裡就要用上notify和wait了。
public class Thread1 {
public static void main(String args[]) {
final Bussiness business = new Bussiness();
Thread a=new Thread(new Runnable(){
@Override
public void run(){
business.SubThread();
}
});
Thread b=new Thread((new Runnable() {
@Override
public void run() {
business.MainThread();
}
}));
a.start();
b.start();
}
}
class Bussiness {
private static Object LOCK = new Object();
volatile boolean bShouldSub = true;//這裡相當於定義了控制該誰執行的一個訊號燈
public void MainThread() {
for (int i = 0; i < 50; i++) {
synchronized (LOCK) {//notify和wait的物件一定要和synchronized的物件保持一致
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + "+MainThread:i=" + i + ",j=" + j);
}
if (bShouldSub) {
bShouldSub = false;
LOCK.notify();
if(i<49){
try {
LOCK.wait();
}catch (InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
}
}
}
public void SubThread() {
for (int i = 0; i < 50; i++) {
synchronized (LOCK){
for (int j = 0; j < 5; j++) {
System.out.println(Thread.currentThread().getName() + "+SubThread:i=" + i + ",j=" + j);
}
if (!bShouldSub) {
bShouldSub = true;
LOCK.notify();
if(i<49){
try {
LOCK.wait();
} catch (InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
}
}
}
}複製程式碼
各種容器的初始化長度是多少?
使用ArrayList初始化時注意事項?(自動擴充機制方面,原理實現)?
好了,一面到此結束,歷時一個半小時,淚崩,懵逼!(關鍵下午還有課!!!遲到了!!!)
總結一點,閱讀原始碼很重要!(Spring+SpringMVC+Mybatis)
上面題目的部分答案,歡迎前往歷年阿里面試題彙總(2017年不斷更新中)、各大公司Java後端開發面試題總結查閱
更多內容,可關注我的個人公眾號