2019螞蟻金服Java必問面試題(一面)

一面
一、自我介紹、本身作的項目和技術領域java

二、項目中的監控:那個監控指標常見的有哪些?web

答:CPU、內存、IO 等等。建議下載個nmon工具,裏面有各個指標。面試

數據庫:Mysql(緩存命中、索引、單條SQL性能、數據庫線程數、數據池鏈接數)算法

中間件:1.消息二、負載均衡三、緩存(包括線程數、鏈接數、日誌)。spring

網絡: 吞吐量、吞吐率sql

應用: jvm內存、日誌、Full GC頻率數據庫

三、註冊中心你瞭解了哪些?編程

答:Consul 、Eureka、ZooKeeperjson

四、項目用 Spring 比較多,有沒有了解 Spring 的原理?AOP 和 IOC 的原理api

答:

(1). IoC(Inversion of Control)是指容器控制程序對象之間的關係,而不是傳統實現中,由程序代碼直接操控。控制權由應用代碼中轉到了外部容器,控制權的轉移是所謂反轉。 對於Spring而言,就是由Spring來控制對象的生命週期和對象之間的關係;IoC還有另一個名字——「依賴注入(Dependency Injection)」。從名字上理解,所謂依賴注入,即組件之間的依賴關係由容器在運行期決定,即由容器動態地將某種依賴關係注入到組件之中。

(2). 在Spring的工做方式中,全部的類都會在spring容器中登記,告訴spring這是個什麼東西,你須要什麼東西,而後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其餘須要你的東西。全部的類的建立、銷燬都由 spring來控制,也就是說控制對象生存週期的再也不是引用它的對象,而是spring。對於某個具體的對象而言,之前是它控制其餘對象,如今是全部對象都被spring控制,因此這叫控制反轉。

(3). 在系統運行中,動態的向某個對象提供它所須要的其餘對象。

(4). 依賴注入的思想是經過反射機制實現的,在實例化一個類時,它經過反射調用類中set方法將事先保存在HashMap中的類屬性注入到類中。 總而言之,在傳統的對象建立方式中,一般由調用者來建立被調用者的實例,而在Spring中建立被調用者的工做由Spring來完成,而後注入調用者,即所謂的依賴注入or控制反轉。 注入方式有兩種:依賴注入和設置注入; IoC的優勢:下降了組件之間的耦合,下降了業務對象之間替換的複雜性,使之可以靈活的管理對象。

五、AOP(Aspect Oriented Programming)

(1). AOP面向方面編程基於IoC,是對OOP的有益補充;

(2). AOP利用一種稱爲「橫切」的技術,剖解開封裝的對象內部,並將那些影響了 多個類的公共行爲封裝到一個可重用模塊,並將其名爲「Aspect」,即方面。所謂「方面」,簡單地說,就是將那些與業務無關,卻爲業務模塊所共同調用的 邏輯或責任封裝起來,好比日誌記錄,便於減小系統的重複代碼,下降模塊間的耦合度,並有利於將來的可操做性和可維護性。

(3). AOP表明的是一個橫向的關 系,將「對象」比做一個空心的圓柱體,其中封裝的是對象的屬性和行爲;則面向方面編程的方法,就是將這個圓柱體以切面形式剖開,選擇性的提供業務邏輯。而 剖開的切面,也就是所謂的「方面」了。而後它又以巧奪天工的妙手將這些剖開的切面復原,不留痕跡,但完成了效果。

(4). 實現AOP的技術,主要分爲兩大類:一是採用動態代理技術,利用截取消息的方式,對該消息進行裝飾,以取代原有對象行爲的執行;二是採用靜態織入的方式,引入特定的語法建立「方面」,從而使得編譯器能夠在編譯期間織入有關「方面」的代碼。

(5). Spring實現AOP:JDK動態代理和CGLIB代理 JDK動態代理:其代理對象必須是某個接口的實現,它是經過在運行期間建立一個接口的實現類來完成對目標對象的代理;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現原理相似於JDK動態代理,只是它在運行期間生成的代理對象是針對目標類擴展的子類。CGLIB是高效的代碼生成包,底層是依靠ASM(開源的java字節碼編輯類庫)操做字節碼實現的,性能比JDK強;須要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ註解驅動的切面實際上底層也是經過動態代理實現的。

六、Spring Boot除了自動配置,相比傳統的 Spring 有什麼其餘的區別?

爲Spring 生態系統的開發提供一種更簡潔的方式,提供了不少非功能性特性,例如:嵌入式 Server,Security,統計,健康檢查,外部配置等等,主要體如今如下幾點:

(1).Spring Boot能夠創建獨立的Spring應用程序;

(2).內嵌瞭如Tomcat,Jetty和Undertow這樣的容器,也就是說能夠直接跑起來,用不着再作部署工做了;

(3).無需再像Spring那樣搞一堆繁瑣的xml文件的配置;

(4).能夠自動配置Spring。SpringBoot將原有的XML配置改成Java配置,將bean注入改成使用註解注入的方式(@Autowire),並將多個xml、properties配置濃縮在一個appliaction.yml配置文件中。

(5).提供了一些現有的功能,如量度工具,表單數據驗證以及一些外部配置這樣的一些第三方功能;

(6).整合經常使用依賴(開發庫,例如spring-webmvc、jackson-json、validation-api和tomcat等),提供的POM能夠簡化Maven的配置。當咱們引入核心依賴時,SpringBoot會自引入其餘依賴。

七、Spring Cloud 有了解多少?

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,均可以用Spring Boot的開發風格作到一鍵啓動和部署。Spring Cloud並無重複製造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,經過Spring Boot風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分佈式系統開發工具包。

八、Spring Bean 的生命週期

一個Bean從建立到銷燬,若是是用BeanFactory來生成,管理Bean的話

Spring上下文中的Bean也相似,以下

(1)實例化一個Bean--也就是咱們常說的new;

(2)按照Spring上下文對實例化的Bean進行配置--也就是IOC注入;

(3)若是這個Bean已經實現了BeanNameAware接口,會調用它實現的setBeanName(String)方法,此處傳遞的就是Spring配置文件中Bean的id值

(4)若是這個Bean已經實現了BeanFactoryAware接口,會調用它實現的setBeanFactory(setBeanFactory(BeanFactory)傳遞的是Spring工廠自身(能夠用這個方式來獲取其它Bean,只需在Spring配置文件中配置一個普通的Bean就能夠);

(5)若是這個Bean已經實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文(一樣這個方式也能夠實現步驟4的內容,但比4更好,由於ApplicationContext是BeanFactory的子接口,有更多的實現方法);

(6)若是這個Bean關聯了BeanPostProcessor接口,將會調用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor常常被用做是Bean內容的更改,而且因爲這個是在Bean初始化結束時調用那個的方法,也能夠被應用於內存或緩存技術;

(7)若是Bean在Spring配置文件中配置了init-method屬性會自動調用其配置的初始化方法。

(8)若是這個Bean關聯了BeanPostProcessor接口,將會調用postProcessAfterInitialization(Object obj, String s)方法、;

注:以上工做完成之後就能夠應用這個Bean了,那這個Bean是一個Singleton的,因此通常狀況下咱們調用同一個id的Bean會是在內容地址相同的實例,固然在Spring配置文件中也能夠配置非Singleton,這裏咱們不作贅述。

九、HashMap 和 hashTable 區別?

區別:Hashtable是線程安全的,效率比較低

Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的註釋中有說明

Hashtable默認的初始大小爲11,以後每次擴充,容量變爲原來的2n+1。

HashMap默認的初始化大小爲16。以後每次擴充,容量變爲原來的2倍

Hashtable在計算元素的位置時須要進行一次除法運算,而除法運算是比較耗時的

HashMap爲了提升計算效率,將哈希表的大小固定爲了2的冪,這樣在取模預算時,不須要作除法,只須要作位運算。位運算比除法的效率要高不少。

HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary類。不過它們都實現了同時實現了map、Cloneable(可複製)、Serializable(可序列化)這三個接口

十、Object 的 hashcode 方法重寫了,equals 方法要不要改?

不須要,Ojbect類中有兩個方法equals、hashCode,這兩個方法都是用來比較兩個對象是否相等的,若是兩個對象相等(equal),那麼必須擁有相同 的哈希碼(hash code)

即便兩個對象有相同的哈希值(hash code),他們不必定相等

重寫equals()方法就必須重寫hashCode(),但重寫hashcode方法不必定要重寫equals方法

十一、Hashmap 線程不安全的出現場景

用ConcurrentHashMap 線程安全

多線程處理時hashmap線程不安全

首先hashmap裏這個size沒有用volatile關鍵字修飾,表明這不是一個內存可見的變量,線程操做數據的時候通常是從主存拷貝一個變量副本進行操做,操做完成事後在把size的值寫回到主存size的

線程不安全問題應該屬於併發問題之一的,屬於相對高級的問題了。這個時候的問題已經不只僅侷限於代碼層面了,不少時候須要結合JVM一塊兒分析了

十二、JDK 中有哪幾個線程池?

順帶把線程池講了個遍

JUC提供了調度器對象Executors來建立線程池,可建立的線程池有四種

(1)newFixedThreadPool建立一個指定工做線程數量的線程池。每當提交一個任務就建立一個工做線程,若是工做線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中。

(2)newCachedThreadPool建立一個可緩存的線程池。這種類型的線程池特色是:

1).工做線程的建立數量幾乎沒有限制(其實也有限制的,數目爲Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。

2).若是長時間沒有往線程池中提交任務,即若是工做線程空閒了指定的時間(默認爲1分鐘),則該工做線程將自動終止。終止後,若是你又提交了新的任務,則線程池從新建立一個工做線程。

(3)newSingleThreadExecutor建立一個單線程化的Executor,即只建立惟一的工做者線程來執行任務,若是這個線程異常結束,會有另外一個取代它,保證順序執行(我以爲這點是它的特點)。單工做線程最大的特色是可保證順序地執行各個任務,而且在任意給定的時間不會有多個線程是活動的 。

(4)newScheduleThreadPool建立一個定長的線程池,並且支持定時的以及週期性的任務執行,相似於Timer。(這種線程池原理暫還沒徹底瞭解透徹)

1三、查看 SQL 是否是使用了索引?(有什麼工具)

在select語句前加上EXPLAIN便可

1四、TCP 和 UDP 的區別?TCP 數據傳輸過程當中怎麼作到可靠的?

UDP(User Data Protocol,用戶數據報協議)是與TCP相對應的協議。它是屬於TCP/IP協議族中的一種

(1)爲了保證數據包的可靠傳遞,發送方必須把已發送的數據包保留在緩衝區;

(2)併爲每一個已發送的數據包啓動一個超時定時器;

(3)如在定時器超時以前收到了對方發來的應答信息(多是對本包的應答,也能夠是對本包後續包的應答),則釋放該數據包占用的緩衝區;

(4)不然,重傳該數據包,直到收到應答或重傳次數超過規定的最大次數爲止。

(5)接收方收到數據包後,先進行CRC校驗,若是正確則把數據交給上層協議,而後給發送方發送一個累計應答包,代表該數據已收到,若是接收方正好也有數據要發給發送方,應答包也可方在數據包中捎帶過去。

1五、說下你知道的排序算法吧

常見的內部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸併排序、快速排序、堆排序、基數排序等

1六、查找一個數組的中位數?

經過二分查找法來找中位數

基本思想是:假設ar1[i]是合併後的中位數,那麼ar1[i]大於ar1[]中前i-1個數,且大於ar2[]中前j=n-i-1個數。經過ar1[i]和ar2[j]、ar2[j+1]兩個數的比較,在ar1[i]的左邊或者ar1[i]右邊繼續進行二分查找。對於兩個數組 ar1[] 和ar2[], 先在 ar1[] 中作二分查找。若是在ar1[]中沒找到中位數, 繼續在ar2[]中查找。

算法流程:

1) 獲得數組ar1[]最中間的數,假設下標爲i.

2) 計算對應在數組ar2[]的下標j,j = n-i-1

3) 若是 ar1[i] >= ar2[j] and ar1[i] <= ar2[j+1],那麼 ar1[i] 和 ar2[j] 就是兩個中間元素,返回ar2[j] 和 ar1[i] 的平均值

4) 若是 ar1[i] 大於 ar2[j] 和 ar2[j+1] 那麼在ar1[i]的左部分作二分查找(i.e., arr[left ... i-1])

5) 若是 ar1[i] 小於 ar2[j] 和 ar2[j+1] 那麼在ar1[i]的右部分作二分查找(i.e., arr[i+1....right])

6) 若是到達數組ar1[]的邊界(left or right),則在數組ar2[]中作二分查找

時間複雜度:O(logn)。
螞蟻完整面試題(一面、二面)、學習視頻、大廠面試題、java核心資料整理:https://shimo.im/docs/TC9Jq63Tp6HvTXdg/

相關文章
相關標籤/搜索