JAVA面試題目(一)--阿里巴巴--2019-08-04

一、Java基礎和高級

1.String類爲什舉是final的。

   用處有三:1)常量池共享 2)線程安全 3)hashCode的鍵值最好選擇

2.HashMap的源碼,實現原理,底層結構。

   HashMap底層使用數組+鏈表+紅黑樹實現,putVal在鏈表結點數大於8的時候自旋成紅黑樹,使得查詢速度由O(n)提升爲O(log n)

3.反射中,Class.forName 和classloader的區別

   Class.forName不但會加載.class文件到jvm中還會執行static塊代碼,classloader只會將.class文件加載到jvm只有當執行newInstance的時候都會執行static代碼。

4.session和cookie的區別和聯繫,session的生命週期,多個服務部署時session管理。

   session存儲在server端,cookie存儲在客戶端,cookie利用server返回的信息保存,cookie如果不設過期時間會長久保留在客戶端,否則瀏覽器關閉的時候就會清空cookie信息。server當瀏覽器關閉的時候session註銷。

   多個服務器部署時可以有幾種方案:1)session信息保存到cookie中,瀏覽器訪問服務時帶回即可。2)session請求粘貼,利用負載將同一個客戶端的請求都發到一個server上。3)利用獨立的redis緩存服務器來存儲session信息,實現共享。redis可以做成集羣,定時copy session信息

5.Java中的隊列都有哪些,有什舉區別。

   Java中隊列是一個先進先出的數據結構,通常不能隨機訪問,根據實現的方式不同主要有兩種方式:數組 & 鏈表。如下圖:

在併發編程中,保證線程安全的隊列有阻塞隊列和非阻塞隊列之分。

   阻塞隊列在隊列爲空時或隊列滿的時候,獲取元素的線程會等待隊列變爲非空,當隊列爲滿時,存儲元素的線程會等待隊列可用。阻塞隊列有以下幾種:

  • ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。
  • LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。
  • PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。
  • DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。
  • SynchronousQueue:一個不存儲元素的阻塞隊列。
  • LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。
  • LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。

阻塞隊列的實現原理:添加元素的最後一行,notEmpty.signal();表示添加完元素後,調用signal通知等待的線程,隊列不空了,可以來取東西的。移除元素的最後一行,也是這樣的。

非阻塞的方式可以循環使用CAS的方式來實現,非阻塞隊列的一個實現方式爲concurrentLinkedQueue,這是一個基於鏈接節點的無界線程安全隊列,入隊和出隊操作均使用CAS(Compare and set) 更新,這樣允許多個線程併發執行,並且不會因爲加鎖而阻塞線程。 

6.Java的內存模型以及GC算法

   JAVA 1.8內存模型,JVM內存共分爲虛擬機棧、堆、方法區、程序計數器、本地方法棧,如下圖所示:

1. 每個線程都有一個私有的棧,隨着線程的創建而創建。棧裏面存放着棧楨的東西,棧楨中存放了局部變量表。當棧調用深度超過JVM所允許的範圍內之後,會拋出StackOverflow異常。

2.本地方法棧,這裏面主要存放着虛擬機用到的native方法相關,一般不需要考慮。

3.PC寄存器,JVM支持多個線程同時運行,每個線程都有自己的程序計數器。

4. 堆,堆內存是JVM所有線程共享的部分,在虛擬機啓動的時候創建。所有的對象和數組都在堆上進行分配,這部分的空間可以通過GC來回收,當申請不到空間後就會拋出OutOfMemoryError.

5.方法區,該區也是所有線程共享,主要存儲類的信息、常量池、方法數據、方法代碼等。方法區邏輯上屬於堆的一部分,但是爲了與堆進行區分,通常又叫“非堆”。

GC算法主要分爲:1)標記-清理。 2)複製算法。3)標記-整理算法 4)分類算法。

1)標記-清理,分爲兩個階段,一:標記所需要回收的對象,二:回收被標記的對象。標記算法分爲引用計數算法和可達性算法,由於引用計數算法無法解決循環引用 的問題,所以 一般會採用可達性算法。這種算法雖然清理了空間,但是空間不連續,利用率低。

2)複製算法,它將內存分爲現塊相等的區域,每次使用一塊,當這一塊使用完了,就將還存活的對象按照原有的順序複製到另一塊內存中,然後就當前空間一次性清理掉。內存開銷較大。

3)標記-整理算法,標記跟1)一樣,整理是將存活的對象內存一段移動,整理出一塊較大的連續內存空間

 

7.Java7、Java8的新特性

  Java7. 子類自動裝箱。整型類型表達可用"_”拼接表達。catch多個exception. file文件讀自動關閉。

   Java8 lamada表達式。信息stream的使用

8.Java 數組和鏈表兩種結構的操作效率,在哪些情冴下(從開頭開始,從結尾開始,從中間開始),哪些操

作(插入,查找,刪除)的效率高

   數組查詢時間O(1), 鏈表查詢時間O(n) , 插入、刪除效率高。

9.Java內存泄露的問題調查定位:jmap,jstack的使用等等

 

二、spring框架

spring框架中需要引用哪些jar包,以及這些jar包的用途

spring-web:開發web應用的時候會用到,包括自動載入webapplicationContext特性的類。

springg-core: 這個jar文件包含spring框架基本的核心工具類,

spring-aop:若要使用spring aop特性所需要的類

spring-beans:它包含訪問配置文件,創建和管理bean以及進行控制反轉的各個工具類。

spring-webmvc:包含mvc框架相關的核心類,包括國際化、標籤、theme、視圖展示、

spring-expression

spring-context: 這個包爲spring提供擴展

srpingMVC的原理:

SpringMVC的工作原理圖:

SpringMVC流程

1、  用戶發送請求至前端控制器DispatcherServlet。

2、  DispatcherServlet收到請求調用HandlerMapping處理器映射器。

3、  處理器映射器找到具體的處理器(可以根據xml配置、註解進行查找),生成處理器對象及處理器攔截器(如果有則生成)一併返回給DispatcherServlet。

4、  DispatcherServlet調用HandlerAdapter處理器適配器。

5、  HandlerAdapter經過適配調用具體的處理器(Controller,也叫後端控制器)。

6、  Controller執行完成返回ModelAndView。

7、  HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet。

8、  DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器。

9、  ViewReslover解析後返回具體View。

10、DispatcherServlet根據View進行渲染視圖(即將模型數據填充至視圖中)。

11、 DispatcherServlet響應用戶。

組件說明:

以下組件通常使用框架提供實現:

DispatcherServlet:作爲前端控制器,整個流程控制的中心,控制其它組件執行,統一調度,降低組件之間的耦合性,提高每個組件的擴展性。

HandlerMapping:通過擴展處理器映射器實現不同的映射方式,例如:配置文件方式,實現接口方式,註解方式等。 

HandlAdapter:通過擴展處理器適配器,支持更多類型的處理器。

ViewResolver:通過擴展視圖解析器,支持更多類型的視圖解析,例如:jsp、freemarker、pdf、excel等。

springMVC註解的意思:

spring中beanFactory和ApplicationContext的聯繫和區別

beanFactory是spring最底層的功能,提供了容器功能,只提供了實例化對象和取對象的基本功能,它是延遲加載的策略,只有當調用的時候spring纔會創建對象。

ApplicationContext繼承beanFactory接口,是一種更高級的容器,提供了更多的功能:1)國際化 2)訪問資源 3)消息發送及響應。4)aop.

spring注入的幾種方式

三種方式:1)屬性的set方法注入 2)使用構造器注入 3)使用Field注入(註解方式)

spring如何實現事物管理的

spring aop 面向切面編程實現需要開戶事務的service攔截。

springIOC和AOP的原理

IOC 原理參考:https://mp.csdn.net/postedit/97909819

AOP原理參考:https://mp.csdn.net/postedit/97926469

spring中循環注入的方式

Spring 循環注入其實就是循環依賴。比如多個對象之間的相互依賴。出現循環注入的方式有三種:

構造器注入,setting注入,自動注入。

構造器注入: 此依賴無法解決、

setting是通過spring容器提前暴露剛完成構造器注入但是未完成其他步驟(如setting注入等)的bean來完成的,而且只能解決單例作用域的bean循環依賴。

Spring的beanFactory和factoryBean的區別

beanFactory是Ioc容器的核心接口,它的職責包括:實例化 、定位、配置應用程序中的對象的建立這些對象間的依賴、

ApplicationContext是beanFactory的擴展,功能得到進一步的增強,與aop集成,用得最多的beanFactory的子類是ClassPathXmlApplicationContext..

Spring爲我們提供了兩種bean,一種是普通的bean,一種是FactoryBean,實現了FactoryBean接口的類有能力改變bean的行爲。FactoryBean希望你實現了它之後返回一些內容。spring會按照這些內容生成bean

Spring的事務隔離級別,實現原理

Spring事務的隔離級別是與數據庫保持一致的

隔離級別 隔離級別的值 導致的問題
Read-Uncommitted 0 導致髒讀
Read-Committed 1 避免髒讀,允許不可重複讀和幻讀
Repeatable-Read 2 避免髒讀,不可重複讀,允許幻讀
Serializable 3 串行化讀,事務只能一個一個執行,避免了髒讀、不可重複讀、幻讀。執行效率慢,使用時慎重

Spring事務的傳播機制,有大概7種:

常量名稱 常量解釋
PROPAGATION_REQUIRED 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇,也是 Spring 默認的事務的傳播。
PROPAGATION_REQUIRES_NEW 新建事務,如果當前存在事務,把當前事務掛起。新建的事務將和被掛起的事務沒有任何關係,是兩個獨立的事務,外層事務失敗回滾之後,不能回滾內層事務執行的結果,內層事務失敗拋出異常,外層事務捕獲,也可以不處理回滾操作
PROPAGATION_SUPPORTS 支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY 支持當前事務,如果當前沒有事務,就拋出異常。
PROPAGATION_NOT_SUPPORTED 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER 以非事務方式執行,如果當前存在事務,則拋出異常。
PROPAGATION_NESTED

如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。

對 Spring 的理解,非單例注入的原理?它的生命週期?循環注入的原理,aop 的實現原理,說說 aop 中的幾個術語,它們是怎舉相互工作的?

spring boot特性,優勢,適用場景等

 

三、java多線程常見問題

1.Java創建線程後,直接調用start()方法和run()的區別

   在同一個線程內部可多次執行run方法,start只能啓動一次。

    start真正的多線程運行,這裏無須等待run方法體執行完成,就可以繼續執行新的thread.start方法 。

    run只是普通方法來使用,程序還要順序執行,要等待run方法執行完畢後,纔可以繼續執行下面的代碼。

2.常用的線程池模式以及不同線程池的使用場景

 java使用Executor管理線程池,底層使用ThreadPoolExecutor

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

corePoolSize:池中所保存的線程數,包括空閒線程

maximumPoolSize-池中允許的最大線程數。

keepAliveTime - 當線程數大於核心時,多於的空閒線程最多存活時間

unit - keepAliveTime 參數的時間單位。

workQueue - 當線程數目超過核心線程數時用於保存任務的隊列

RejectedExecutionHandler 線程的飽和策略,默認的是abortPolicy(表示無法處理新任務),這時會拋出handler裏面的rejectedExecution方法通知調用者,並拋出rejectedExecutionException。還有另外3個策略:DiscardPolicy/DiscardOldestPolicy/CallerRunsPolicy,分別解釋如下:

(1)CallerRunsPolicy:用調用者所在的線程由處理原任務改爲處理新任務
(2)DiscardPolicy:拋棄新任務
(3)DiscardOldestPolicy:丟棄隊列中最近的任務,並執行新任務

其它的還有幾個executor實現類:

newCachedThreadPoo l創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
newFixedThreadPool  創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool  創建一個定長線程池,支持定時及週期性任務執行。
newSingleThreadExecutor  創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 

 

3.newFixedThreadPool此種線程池如果線程數達到最大值後會怎舉辦,底層原理。

newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待,它採用的是LinkedBlockingQueue,是無界隊列,任務可以一起添加進去。所以newFixedThreadPool會保持nThread個線程在線程池中,而且是按順序從LinkedBlockingQueue中取任務。若提交的任務比完成的任務時間快時,會一直添加任務,導致LinkedBlockingQueue一直增長,消耗大量內存。

 

4.多線程之間通信的同步問題。

     

多線程之間的通信主要是爲了解決同步和異步的問題。

   實現方法:線程間的通信可以通過:1)互斥鎖(mutex)。 2)信號量(semphore)。 3)條件變量(condition)。4)讀寫鎖(reader-writer lock)

   互斥鎖:是一個變量,它有Lock和unlock兩個狀態。互斥鎖一般會被設置成全局變量,打開的互斥鎖可以由某個線程獲得,一旦獲得,這個互斥鎖會再鎖上,這樣,只有該線程纔能有權打開。其它想要獲取互斥鎖的線程,要等到互斥鎖再次打開的時候。

   信號量。信號量和互斥鎖的區別是,互斥鎖只允許一個線程進行臨界區,而信號量允許多個線程同時進入臨界區。

   條件變量:condition

   讀寫鎖:volatile修飾的變量直接存放在main memory裏面,volatile能保證所修飾的變量對於多個線程可見,即只要被修改,其它線程就一定能讀到最新的值。

   JAVA通過wait . notify, notifyAll三個方法來解決線程間通信問題。wait可以使調用該方法的線程釋放共享資源的鎖,然後從運行狀態退出,進入等待隊列,直到再次被喚醒。notify可以使調用該方法的線程獲取共享資源的鎖,進行運行狀態。 

5.瞭解可重入鎖的含義以及ReentrantLock 和synchronized的區別

    可重入鎖的舉例:當一個線程執行到synchronized方法method1時,而method1中調用了另一個synchronized方法,method2,此線程不需要重新申請一把鎖可以直接執行method2. 

   Synchronized 和 ReentrantLock都是可重入鎖。Synchronized是不可中斷鎖,而ReentrantLock是可中斷鎖,如果線程a正在執行鎖中的代碼時間過長,可以自己中斷或者在別的線程上中中斷它。而synchronized是不可以的。Synchornized和ReentrantLock都是非公平鎖,但是ReentrantLock可以開啓公平鎖。

6.同步的數據結構,例如 concurrentHashMap 的源碼理解以及內部實現原理,爲什舉他是同步的且效率高

   ConcurrentHashMap: 
   

static class Node<K,V>{

      final int hash;

      final K key;

      volatile V val;

     volatile Node<K,V> next;

   }

7.atomicinteger 和volatile等線程安全操作的關鍵字的理解和使用

8.線程間通信,wait和notify

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章