一、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