1.MyBatis是什么?
-
Mybatis是一個半ORM(對象關系映射)框架,它內部封裝了JDBC,加載驅動、創建連接、創建statement等繁雜的過程,開發者開發時只需要關注如何編寫SQL語句,可以嚴格控制
sql
執行性能,靈活度高。 -
作為一個半ORM框架,MyBatis 可以使用 XML 或注解來配置和映射原生信息,將 POJO映射成數據庫中的記錄,避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
-
通過xml 文件或注解的方式將要執行的各種
statement
配置起來,並通過java對象和statement
中sql
的動態參數進行映射生成最終執行的sql
語句,最后由mybatis框架執行sql並將結果映射為java對象並返回。(從執行sql到返回result的過程)。 -
由於MyBatis專注於SQL本身,靈活度高,所以比較適合對性能的要求很高,或者需求變化較多的項目,如互聯網項目。
優點:
-
基於SQL語句編程,相當靈活,不會對應用程序或者數據庫的現有設計造成任何影響,SQL寫在XML里,解除sql與程序代碼的耦合,便於統一管理;提供XML標簽,支持編寫動態SQL語句,並可重用。
-
與JDBC相比,減少了50%以上的代碼量,消除了JDBC大量冗余的代碼,不需要手動開關連接;
-
很好的與各種數據庫兼容(因為MyBatis使用JDBC來連接數據庫,所以只要JDBC支持的數據庫MyBatis都支持)。
-
能夠與Spring很好的集成;
-
提供映射標簽,支持對象與數據庫的ORM字段關系映射;提供對象關系映射標簽,支持對象關系組件維護。
缺點:
-
SQL語句的編寫工作量較大,尤其當字段多、關聯表多時,對開發人員編寫SQL語句的功底有一定要求。
-
SQL語句依賴於數據庫,導致數據庫移植性差,不能隨意更換數據庫。
Mybatis和Hibernate的區別
-
Mybatis
和hibernate
不同 ,它不完全是一個 ORM 框架 ,因為 MyBatis 需要程序員自己編寫 Sql 語句,Mybatis
直接編寫原生態sql
, 可以嚴格控制sql
執行性能, 靈活度高, 非常適合對關系數據模型要求不高的軟件開發,因為這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。 - 映射關系:
- MyBatis 是一個半自動映射的框架,配置Java對象與sql語句執行結果的對應關系,多表關聯關系配置簡單
- Hibernate 是一個全表映射的框架,配置Java對象與數據庫表的對應關系,多表關聯關系配置復雜
2.#{}和¥{}的區別是什么?
#{ } 是占位符,預編譯處理,${ } 是拼接符,字符串替換
Mybatis在處理#{ }時,會對sql語句進行預處理,將sql中的#{ }替換為?號,調用PreparedStatement的set方法來賦值;
Mybatis在處理${ }時,就是把${ }直接替換成變量的值;
--Mybatis在處理#{}時
select id,name,age from student where id =#{id}
當前端把id值1傳入到后台的時候,就相當於:
select id,name,age from student where id ='1'
--Mybatis在處理${}時
select id,name,age from student where id =${id}
當前端把id值1傳入到后台的時候,就相當於:
select id,name,age from student where id = 1
3.MyBatis的編程步驟是什么樣的?
1.創建SqlSessionFactory
2.通過SqlSessionFactory創建SqlSession
3.通過sqlsession執行數據庫操作
4.調用session.commit()提交事務
5.調用session.close()關閉會話
4.Mybatis都有哪些Executor執行器?
三種基本的Executor執行器,SimpleExecutor 普通的執行器,執行update和select,就開啟Statement對象,用完立刻關閉。
ReuseExecutor 重用預處理語句
BatchExecutor 重用語句並批量更新
5.Mybatis是否支持延遲加載?如果支持,他的實現原理是什么?
Mybatis僅支持association關聯對象和collection關聯集合對象的延遲加載,association指的就是一對一,collection值得就是一對多查詢。
它的原理是,使用CGLIB創建目標對象的代理對象,當調用目標方法時,進入攔截器方法,比如調用a.getB().getName(),攔截器invoke()方法發現a.getB()是null值,那么就會單獨發送事先保存好的查詢關聯B對象的sql,把B查詢上來,然后調用a.setB(b),於是a的對象b屬性就有值了,接着完成a.getB().getName()方法的調用。這就是延遲加載的基本原理。
6.模糊查詢like語句該怎么寫?
使用CONCAT('%',#{question}.'%') 使用CONCAT()函數
使用bind標簽:
<select id="listUserLikeUsername" resultType="com.jourwon.pojo.User">
<bind name="pattern" value="'%' + username + '%'" />
select id,sex,age,username,password from person where username LIKE #{pattern}
</select>
7.當實體類中的屬性名和表中的字段名不一樣,怎么辦
1.通過<resultMap>來映射字段名和實體類屬性名的一一對應的關系
<select id="getOrder" parameterType="int" resultMap="orderResultMap">
select * from orders where order_id=#{id}
</select>
<resultMap type="com.jourwon.pojo.Order" id="orderResultMap">
<!–用id屬性來映射主鍵字段–>
<id property="id" column="order_id">
<!–用result屬性來映射非主鍵字段,property為實體類屬性名,column為數據庫表中的屬性–>
<result property ="orderno" column ="order_no"/>
<result property="price" column="order_price" />
</reslutMap>
2.起別名
通常一個Xml映射文件,都會寫一個Dao接口與之對應,請問,這個Dao接口的工作原理是什么?Dao接口里的方法,參數不同時,方法能重載嗎
Dao接口的工作原理是JDK動態代理,Mybatis運行時會使用JDK動態代理為Dao接口生成代理proxy對象,代理對象proxy會攔截接口方法,轉而執行MappedStatement所代表的sql,然后將sql執行結果返回。
Dao接口里的方法,是不能重載的,因為是全限名+方法名的保存和尋找策略
Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重復?
不同的Xml映射文件,配置了namespace,id可以重復,沒有配置namespace,id就不能重復
簡述Mybatis的Xml映射文件和Mybatis內部數據結構之間的映射關系?
Mybatis將所有Xml配置信息都封裝到All-In-One重量級對象Configuration內部。在Xml映射文件中,<parameterMap>標簽會被解析為ParameterMap對象,其每個子元素會被解析為ParameterMapping對象。<resultMap>標簽會被解析為ResultMap對象,其每個子元素會被解析為ResultMapping對象。每一個<select>、<insert>、<update>、<delete>標簽均會被解析為MappedStatement對象,標簽內的sql會被解析為BoundSql對象。
Mybatis是如何將sql執行結果封裝為目標對象並返回的?都有哪些映射形式?
第一種是使用<resultMap>標簽,逐一定義列名和對象屬性名之間的映射關系。
第二種是使用sql列的別名功能,將列別名書寫為對象屬性名,比如T_NAME AS NAME,對象屬性名一般是name,小寫,但是列名不區分大小寫,Mybatis會忽略列名大小寫,智能找到與之對應對象屬性名,你甚至可以寫成T_NAME AS NaMe,Mybatis一樣可以正常工作。
有了列名與屬性名的映射關系后,Mybatis通過反射創建對象,同時使用反射給對象的屬性逐一賦值並返回,那些找不到映射關系的屬性,是無法完成賦值的。
Xml映射文件中,除了常見的select|insert|updae|delete標簽之外,還有哪些標簽?
<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上動態sql的9個標簽,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中<sql>為sql片段標簽,通過<include>標簽引入sql片段,<selectKey>為不支持自增的主鍵生成策略標簽。
有聯合查詢和嵌套查詢。聯合查詢是幾個表聯合查詢,只查詢一次,通過在resultMap里面的association,collection節點配置一對一,一對多的類就可以完成
嵌套查詢是先查一個表,根據這個表里面的結果的外鍵id,去再另外一個表里面查詢數據,也是通過配置association,collection,但另外一個表的查詢通過select節點配置。
Mybatis是否可以映射到Enum枚舉類
mybatis可以映射Enum枚舉類,映射方式為自定義個TypeHandler,實現TypeHandler的setParameter()和getResult()接口方法。TypeHandler有兩個作用,一是完成從java type到jdbc的轉換,二是完成jdbcType到Javatype的轉換。
Mybatis動態sql是做什么的?都有哪些動態sql?能簡述一下動態sql的執行原理不?
Mybatis是如何進行分頁的?分頁插件的原理是什么?
Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的內存分頁,而非物理分頁,可以在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。
分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然后重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。
select * from student,攔截sql后重寫為:select t.* from (select * from student) t limit 0, 10
MyBatis 的分頁功能是基於內存的分頁,即先查詢出所有記錄,再按起始位置和頁面容量取出結果。
MyBatis攔截器原理?
Mybatis提供了一種插件(plugin)的功能,雖然叫做插件,但其實這是攔截器功能。Mybatis允許你在已映射語句執行過程中的某一點進行攔截調用,Mybatis允許使用插件來攔截的方法調用包括:Executor,ParameterHandler,ResultSetHandler,StatementHandler
比如在使用分頁插件來完成Mybatis分頁
分頁插件的原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然后重寫sql,然后在sql語句添加對應的物理分頁語句和物理分頁參數。
看過MyBatis源碼嗎,請說說它的工作流程?
1.加載配置文件
2.生成SqlSessionFactory工廠
3.使用SqlSessionFactory工廠創建SqlSession對象
4.使用SqlSession創建Dao接口的代理對象
5.使用代理對象執行方法
6.關閉SqlSession,釋放資源
什么是字符串常量池? 創建一個字符串時,JVM會首先去字符串常量池查找是否存在這個對象,如果存在,則不創建任何對象,,直接將這個對象的地址返回。如果不存在,就新創建一個對象,然后返回。 字符串常量池是JVM為了提升性能和減少內存消耗針對字符串專門開辟的一塊區域。 為了避免字符串的重復創建
String為什么是不可變的?String在定義時候聲明final類型String類全局變量都定義為private final類型,表明對象一旦初始化,屬性值就無法改變
String對象真的不可變嗎?那么,用什么方式可以訪問私有成員呢? 沒錯,用反射,可以反射出String對象中的value屬性, 進而改變通過獲得的value引用改變數組的結構
String s = new String("xyz");究竟產生了幾個對象,從JVM角度談談?1個或者兩個如果字符串池沒有xyz字符串,會在字符串池中創建,會在堆內存創建如果字符串有xyz字符串,則只會在堆內存中創建
String拼接字符串效率低,你知道原因嗎?比如在循環里面連接字符串,+在for循環內部,每次執行就會創建一個StringBuilder,如果不斷產生會占用大量資源,應該在程序中直接使用StringBuilder來連接字符串,StringBuilder對象直接進行append的話,可以節省創建和銷毀創建對象的時間。
你真的了解String的常見API嗎?獲取字符串的長度 int length()將自負串里面的小寫字母變成大寫 toUpperCase()將字符串里面的大寫字母變成小寫字母toLowerCase()比較兩個字符串 equals截取字符串 substring()連接兩個字符串 contat()替換 replace()
淺析Java中的final關鍵字?final用於聲明類,屬性,方法 ,即屬性不可變,方法不可覆蓋,類不可繼承
淺析Java中的static關鍵字?static關鍵字聲明一個成員變量或者成員方法可以在沒有所屬的類的實例變量的情況下被訪問。Java中static方法不能被覆蓋,方法覆蓋是運行時動態綁定的,static方法是編譯時靜態綁定的
你對Java中的volatile關鍵字了解多少?volatile是保證了可見性,有序性,沒有原子性volatile只是保持線程的可見性,被volatile修飾,也就有兩層含義:1.線程內的修改操作可以立馬被其他線程看到 2.禁止重排序我們通過看被volatile修飾過后的編譯源碼可以看到有一個前綴指令.lock,這就是相當於一個內存屏障。 內存屏障有3個功能:1.保證內存屏障前的指令不會排到內存屏障的后面內存屏障后面的指令不會排到內存屏障的前面 2強制對緩存的修改操作立即寫入主存 3.如果是寫操作,會導致CPU中對應的緩存行失效
i++是線程安全的嗎?如何解決線程安全性?線程不安全,都沒有原子性對i++操作的方法加同步鎖,同時只有一個線程執行i++操作
從字節碼角度深度解析 i++ 和 ++i 線程安全性原理? i++字節碼: j = i++是一個先壓棧,先將本地變量i壓棧,然后本地變量自增1,再將棧頂元素彈出寫到本地變量j內。此時j還是為0. ++i字節碼: j = ++i的操作順序是先將本地變量i自增一,然后再壓棧,最后寫入到j內。也就是此時j為i+1之后的內容。
請談談什么是CAS?Compare and swap 比較並交換CAS(compare and swap, 比較並交換),是原子操作的一種,可用於在多線程編程中實現不被打斷的數據交換操作,從而避免多線程同時改寫某一數據時由於執行順序不確定性以及中斷的不可預知性產生的數據不一致問題。簡單來說,CAS可以保證多線程對數據寫操作時數據的一致性。CAS的思想:三個參數,一個當前內存值V、舊的預期值A、即將更新的值B,當且僅當預期值A和內存值V相同時,將內存值修改為B並返回true,否則什么都不做,並返回false。CAS的缺點:CASABA問題,循環時間長開銷大和只能保證一個共享變量的原子操作。其中ABA問題作為第三部分重點說明下。
從源碼角度看看ArrayList的實現原理? Arraylist是基於數組存儲的,數組有下標,可以通過數組的下標進行一次訪問,所以查詢速度快。增刪效率低,因為定義數組的時候需要定義其長度,不靈活不方便數據的增,刪。geter()和seter()方法快
手寫LinkedList的實現,徹底搞清楚什么是鏈表?LinkedList的底層是鏈表結構,是雙向鏈表。可以通過鏈表中的一個節點,可以訪問到它的前驅節點和后繼節點。所以add()和remove()效率高
Java中方法參數的傳遞規則?值傳遞,如果是基本類型傳遞基本類型的字面值的拷貝,會創建副本,參數如果是引用類型傳遞的是參數所引用的對象在堆中地址值的拷貝,也會產生副本
Java中throw和throws的區別是什么?throw用來明確的拋出一個異常throws用來表明可能拋出的各種異常throw語句用在方法體內,用來明確的拋出一個異常throws用於方法聲明以后,表明可能拋出的各種異常,throws表示出現異常的一種可能性,不一定會發生這種異常。
重載和重寫的區別?重載發生在子類和子類,方法名必須相同,參數列表不同,實現了一個方法,可以實現類似的功能重寫發生在子類與父類,方法名,參數列表必須相同,子類的返回值要小於等於父類,拋出的異常范圍要小於等於父類,子類的訪問修飾符要大於等於父類,public,protected,default,private,父類如果是private,就不可以重寫。父類和子類的方法必須一致
finally語句塊你踩過哪些坑?finally快不管有沒有捕獲異常或者處理異常都是會執行的,finally塊里面不能有return,如果有的話就返回的是finally里面的return的值了
為什么重寫equals方法需同時重寫hashCode方法?重寫了equals方法必須重寫hashCode方法,針對Set和Map集合:1.集合首先判斷存儲對象是不是唯一的 2.集合類判斷兩個對象是否相等,先用equals()方法判斷是否相等,如果為true,還要判斷HashCode返回值是否為true,如果為true,才認為兩個對象相等
equals() 與 == 的區別?相等於如果是基本類型的話比較的值,如果是引用類型,比較的是內存地址equals()如果是Object.equals()和相等於類似,如果是String.equals()比較的值
StringBuffer和StringBuilder的區別,從源碼角度分析?都是可變字符序列,都繼承AbstractStringBuilderStringBuffer效率低,線程安全StringBuilder效率高,線程是不安全的看過StringBuffer源碼可以看到,幾乎所有的方法都加了synchronized,synchronized是用來加鎖的,所以線城是安全的我們通過StringBuilder源碼看到,基本上方法都沒有用synchronized關鍵字修飾,當多線程訪問時候,就會出現線程安全性問題。
你知道HashMap的數據結構嗎?HashMap在jdk1.7底層是數組,鏈表,在jdk1.8是數組,鏈表,紅黑樹
為何HashMap的數組長度一定是2的次冪?
HashMap何時擴容以及它的擴容機制?HashMap是基於Hashing原理的,是通過Put()方法和get()方法來存儲和獲取元素的,HashMap只要不進行Put方法存儲元素之前,HashMap就不會擴容。當用put方法傳遞鍵和值時候,我們先對對象調用Hashcode()方法計算並返回Hashcode,隨后計算並返回的hashcode適用於找到Map數組的bucket位置來存儲對象,如果bucket滿了,就要進行擴容調用resize方法進行擴容,默認的負載因子為0.75,當一個map填滿了75%的bucket時候,就會擴容,擴容后table大小變味了原來的兩倍
HashMap的key一般用字符串,能用其他對象嗎?一般用Integer,String這種不可變類當HashMap當key
HashMap的key和value都能為null么?如果key能為null,那么它是怎么樣查找值的?HashMap的key和value都能為null
HashMap是線程安全的嗎?如何實現線程安全?線程不安全,使用Collections的synchronizedMap方法包裝一下 使用ConcurrentHashmap,使用分段鎖來保證線程安全
從源碼角度分析HashSet實現原理?Hashset是基於HashMap實現的,有放入HashSet中的集合元素實際上由HashMap的key來保存,而HashMap的value則存儲了一個PRESENT,它是一個靜態的Object對象。如果向HashSet中添加一個已經存在的元素,新添加的集合元素不會覆蓋原來已經有的集合元素
HashTable與HashMap的實現原理有什么不同?HashMap基於Hashing原理,是通過put方法和get方法來進行存儲和獲取元素的,使用put來傳遞鍵和值的時候,會先用hashcode方法,計算並返回的hashcode用於找到Map中的bucket位置來存儲對象HashMap線程不安全,底層在jdk1.7是數組,鏈表,在jdk1.8是數組,鏈表,紅黑樹HashTable底層是數組,鏈表,是線程安全的
String方法intern() 你真的會用嗎?intern()方法設計的初衷,就是重用String對象,節省內存消耗,這個方法返回的是 返回字符串對象的規范化表示形式,當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,並且返回此 String 對象的引用
什么是自動拆裝箱?將基本類型用包裝器類型包裝起來將包裝器類型轉換為基本類型
String.valueOf和Integer.toString的區別?相同點:都可以用於把int轉換成String不同點:String.valueOf可以應用到任何數據類型,且不會有異常報出 Integer.toString先將int轉換為Interger型,然后再將Integer轉換成String型
三、Java多線程
線程的生命周期包括哪幾個階段?創建,就緒,運行,阻塞,死亡首先是創建,這個時候線程還沒有調用start方法,調用了start方法,線程進入就緒狀態,還沒有獲取到CPU的執行指令,獲取到了CPU的執行指令也就開始運行了,如果因為一些原因,丟失了CPU執行指令,也就進入了阻塞狀態,這個時候必須回到就緒狀態,等到重新獲得CPU的執行指令,最后狀態是死亡狀態,線程執行完了,線程結束生命周期
多線程有幾種實現方式?繼承Thread類,重寫Thread的run方法,只可以單繼承實現Runnable接口的run方法,並且將Runnable實例傳給Thread類,再讓Thread類去執行run方法。
請談談什么是進程,什么是線程?進程也就是一個程序從創建,運行,消亡的過程一個進程可以有多個線程,每個線程都有自己的程序計數器,本地方法棧,虛擬機棧
啟動線程是用start()方法還是run()方法?用start()方法,開啟Start()方法就會自動啟動run()方法,這才是多線程。調用run()方法啟動的是main底下的run方法,就不是多線程了。
說說線程安全問題,什么實現線程安全,如何實現線程安全?線程安全就是,我們在寫的某的某個代碼塊,比如i++,i初始值為0,第一個線程結果是1,第二個線程為2,這個線程就是安全的,如果線程不安全,那么第一個線程結果是1,第二個線程的結果是1。也就是多個線程執行能夠正常執行,不會混亂。可以用synchronized和lock來解決線程安全問題,
sychronized和Lock的區別?sychronized是原子性內置鎖,是一個關鍵字,lock是一個接口自動釋放鎖,需要手動釋放鎖,否則就會造成死鎖無法判斷獲取鎖的狀態,而lock鎖可以判斷是否獲取到了鎖lock可以中斷等待鎖的線程的狀態,sychronized里等待的線程會一直等待下去,不能夠相應中斷sychronized適合鎖少量的同步代碼,lock適合鎖大量的同步代碼
sleep()和wait()的區別?兩者都可以暫停線程的執行,sleep()方法屬於Thread類中的,wait()方法屬於Object()類sleep通常用於暫停執行,wait通常用於線程間交互/通信調用sleep(),線程不會釋放鎖,調用wait(),線程會放棄鎖
深入分析ThreadLocal的實現原理?
談談對synchronized的偏向鎖、輕量級鎖、重量級鎖的理解?這是鎖的優化,鎖的狀態是由低到高為無鎖,偏向鎖,輕量級鎖,重量級鎖。 無鎖就是沒有鎖,偏向鎖就是通過對象頭的偏向線程ID來對比,輕量級鎖就是通過CAS修改對象頭鎖和自旋來實現的,重量級鎖則是除了擁有鎖擁有的線程,其他全部都塞。
通過三種方式實現生產者消費者模式?通過一個容器來解決生產者和消費者的強耦合關系,生產者生成數據無需等待消費者索取,消費者無需直接索要數據,通過容器來進行操作。使用synchronize以及wait()、notify() 可以自定義一個阻塞隊列,當隊列免了的時候,通過wait(),使生產者線程阻塞,並釋放隊列對象的鎖,然后調用notify()方法可以喚醒消費者線程使用lock和Condition的await()和signal()方法
JVM層面分析sychronized如何保證線程安全的?sychronized是原子性內置鎖,也被稱為監視器鎖,我們通過觀察被sychronized修飾的編譯過后的同步代碼塊發現,有monitor和monitertesxt字節碼指令,執行monitor指令會獲取鎖,如果獲取到了鎖,其他競爭鎖的線程會進入等待序列,執行了monitortext在字節碼指令,鎖會釋放,處於等待隊列中的線程在繼續競爭鎖
如何寫一個線程安全的單例?餓漢式單例模式,在第一次加載時就實例化懶漢式單例模式,在第一次被引用時開始實例化餓漢式比較好
ThreadLocal什么時候會出現OOM的情況?為什么? 1.ThreadLocal是什么?每個線程在對內存中開辟的一塊工作內存,同時把線程的共享數據拷貝了一份放進去,相當於做的本地副本,不會像synchronized一樣每次修改都要同步到主內存中 2.ThreadLocal有什么用?工作線程的數據交互主要是本地數據和主內存數據的交互,當數據存儲在本地內存中,可以大大提高讀取效率,避免了線程阻塞造成的cpu的吞吐下降;在多線程中每個線程中都要維護sesion,可以提高對獨有資源的工作效率; 3.發生內存泄露原因?synchornized是保證了主內存數據的一致,是時間換空間:通過阻塞一個共享變量,共享一小塊內存空間;threadLocal是通過建立線程的副本數據,空間換時間ThreadLocalMap的Key為弱引用,當threadlocal對象被回收(value在ThreadLocalMap調用get、set、remove的時候就會被清除),這時將key設置為null的entry。但是threadlocal一直不會被回收,導致內存的泄露 4.如何避免呢?其實在調用threalocalMap的get/set方法時,會對key=null的entry(threadlocal對象=null)進行回收,也可以在調用結束時調用remove方法進行釋放。
為什么wait, notify 和 notifyAll這些方法不在thread類里面?Wait-notify機制是在獲取對象鎖的前提下不同線程間的通信機制。在Java中,任意對象都可以當作鎖來使用,由於鎖對象的任意性,所以這些通信方法需要被定義在Object類里。
你真的理解CountDownLatch與CyclicBarrier使用場景嗎?CountDownLatch是一個同步的輔助類,允許一個或多個線程,等待其他一組線程完成操作,再繼續執行。CyclicBarrier是一個同步的輔助類,允許一組線程相互之間等待,達到一個共同點,再繼續執行。
出現死鎖,如何排查定位問題?1.在cmd窗口,使用jps指令查詢該類的端口號(pid)2.在使用jstack+pid查看日志(jstack pid)
notify和notifyAll的區別?調用notify()方法只隨機喚醒一個wait線程,這個線程會從等待池進入鎖池,調用notifyAll方法會喚醒所有wait線程,而且會將該對象等待池內的所偶線程移動到鎖池種,等待鎖競爭。
線程池啟動線程submit和execute有什么不同? execute只能執行Runnable類型的任務,沒有返回值 submit可以執行Runnable和Callable類型的任務 submit能獲取返回值,並且處理異常,通過捕獲Future.get()拋出的異常
SimpleDateFormat是線程安全的嗎?如何解決?SinmpleDateFormat是java提供的一個格式化和解析日期的工具類,在java中,可以使用SimpleDateFormat的format方法,將一個Date類型轉化成String類型,並且可以指定輸出格式。線程不安全,被當作了共享變量在多個線程中進行使用,這就出現了線程安全問題。解決:使用局部變量,就不會被多個線程同時訪問到了,避免了線程安全問題 加同步鎖,通過加鎖使多個線程排隊順序執行 如果是Java8,使用DateTimeFormatter代替SimpleDateFormat
請談談ConcurrentHashmap底層實現原理? ConcurrentHashMap在jdk1.7是分段的數組,鏈表,在jdk1.8以后是node數組,鏈表,紅黑樹。線程是安全的,那怎樣實現線程安全的呢?在jdk1.7是分段鎖對整個桶數組進行了分割,多線程訪問容器里面不同數據段的數據,就不會存在鎖競爭,提高了並發訪問率。
當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其方法?不可以
線程池的原理,為什么要創建線程池?創建線程池的方式?原理:我們在代碼中模擬了10個任務,我們配置的核心線程數是5,等待隊列容量為100,所以每次只能存在5個任務同時執行,剩下的5個任務會被放到等待隊列中,當前的5個任務中如果有任務被執行完了,線程池就會去拿新的任務執行。池化的思想主要為了減少每次獲取資源的消耗,提高對資源的利用率,線程池的好處有降低資源的消耗,提高線程的可管理性。通過構造方法實現,通過Executor框架的工具類Executors來實現。
創建線程池有哪幾個核心參數?最大線程數:maxPoolSize核心線程數:corePoolSize任務隊列容量:queueCapacity線程空閑時間:keepAliveTime允許核心線程超時 allowCoreThreadTimeout任務拒絕處理器 rejectedExecutionHandler
synchronized修飾的靜態方法和非靜態方法有什么區別?修飾靜態方法,作用於當前類對象加鎖,進入同步代碼前要獲得當前類對象的鎖修飾非靜態方法,作用於當前實例加鎖,進入同步代碼前要獲得當前實例的鎖
四、Java Web什么是Servlet,Servlet生命周期方法?Servlet就是一個接口,主要負責接收瀏覽器的請求,tomcat服務器調用servlet方法。init()方法 初始化service()方法 運行destory()方法 銷毀
什么Session和Cookie,它們之間有什么聯系?Session是一個會話,當用戶打開瀏覽器訪問一個網站開始,無論在這個網站訪問了多少頁面,點了多少鏈接,都屬於同一個會話。直到瀏覽器關閉,都屬於同一個會話。Cookie是一種瀏覽器和服務器交互數據的方式。之間的聯系:因為Http協議是無狀態的,即每次訪問都是相當於一個新的請求,Session和Cookie就解決了這個問題,當客戶端向服務端發送了一個請求,服務端收到這個請求就會創建一個Session,隨之也會創建一個SeesionID,服務端同時也會創建一個Cookie包含這個SessionID,進行響應給客戶端,客戶端收到了這個響應,就會設置Cookie信息。接下來客戶端每次向同一個網站發送請求時,包含SessionId的cookie信息都會被服務器讀取到。
JSP的八個隱含對象有哪些?Request,Response,out 即請求,響應,輸出pageContext表示當前頁面作用域session 代表當前會話作用域application 代表當前全局作用域config config可以獲取一些在web.xml中初始化的參數page:表示當前對象exception:表示異常對象
JSP的四個域對象的作用范圍?pagecontext:表示當前頁面作用域,有效范圍在當前jsp頁面里session:表示當前會話作用域,有效作用域就是當前會話application:代表全局作用域,有效范圍時應用啟動到應用結束request:有效范圍就是當前請求周期,從http請求發起,到服務器處理結束,返回響應的整個過程
Post和Get請求的區別?本質都是TCP鏈接Post比Get安全,例如用戶登陸時,如果是Get調用會把賬號密碼都顯示在URL中,而Post調用不會顯示Post請求的時候調用的是Service方法后的doPost()方法,Get請求的時候調用的時Service方法后的doGet()方法
轉發和重定向有什么區別?請求轉發Url的地址不會發生改變,是服務端行為。轉發后的頁面可以讀取上一個頁面放在request中的數據。轉發請求一次重定向Url的地址會發生改變,是客戶端行為。重定向相當於直接在瀏覽器打開重定向的地址,跟上一個頁面沒任何關系。重定向至少請求2次
Http1.0和Http1.1的區別是什么?Http1.0默認使用的是短連接,每次請求都要重新建立一次連接。Http1.1默認使用長連接,持續連接有非流水線方式和流水線方式流水線方式是客戶在收到HTTP的響應報文之前就能接着發送新的請求報文,非流水線方式是客戶在收到一個響應報文以后才能發送下一個請求Http1.1新增了一些錯誤狀態響應碼,410表示某個資源被永久性的刪除Http1.1提供了更多的緩存控制策略
攔截器與過濾器的區別?1.過濾器依賴servlet容器,攔截器不依賴servlet容器2.過濾器是基於函數回調,攔截器是基於java的反射機制3.攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用4.在action的生命周期里,攔截器可以被多次調用,而Filter只能在容器初始化時調用一次。
五、JVM面試題 JVM內存區域如何划分?基於jdk1.7,線程共享的有程序計數器,虛擬機棧,本地方法棧 線程私有的有:堆,方法區 直接內存jdk1.8, 線程共享的有:程序計數器,虛擬機棧,本地方法棧 線程私有的:堆 直接內存,元空間
JVM堆中對象是如何創建的?1.類加載檢查:若對象對應的類已經經過加載,鏈接,初始化,則進入下一步。2.分配內存 3.初始化4.設置對象頭5.執行init方法
JVM對象的結構?對象頭,實例數據,對齊填充
JVM垃圾回收-如何判斷對象是否是垃圾對象?1.可達性分析算法,對象到GC root 沒有引用鏈相連,說明是可以回收的2.引用計數法算法,給對象添加一個引用計數器,每當有一個地方引用對象時,計數器加1,當引用失效的時候,引用計數器的值減1,當引用計數器為0,就可以回收
JVM垃圾回收算法有哪些?標記-清除算法標記-復制算法標記-整理算法分代收集算法JVM類的加載器有哪些?啟動類加載器,擴展類加載器,應用程序類加載器
JVM垃圾收集器有哪些?新生代有Serial,ParNew,Paraller老年代有Serial Old,Paraller Old,G1,CMS
JVM內存是如何分配的? 計算對象占用的空間大小,在堆中划分內存 1.若堆內存規整(使用標記整理算法進行GC),采用指針碰撞法 2.若堆內存不規整(使用標記清楚算法進行GC會殘留下空間碎片),采用空閑列表
從一道面試題分析類的加載過程?加載,鏈接(驗證,准備,解析),初始化,使用,卸載
JVM雙親委派機制?1.如果一個類加載器收到了類加載器請求,他並不貴在即先去加載,而是把這個請求委托給父類的加載器去執行;2.如果父類加載器還存在父類加載器,則進一步向上委托,依次遞歸,請求最終到達頂層的啟動類加載器;3.如果父類加載器可以完成類加載任務,就成功返回,若父類加載器無法完成此加載任務,子加載器才嘗試自己去加載。
JVM可以作為GC Root的對象有哪些?1.本地方法棧native方法引用的對象2.棧中引用的對象3.靜態變量,常量引用的對象
哪些情況會導致Full GC?老生代無法分配空間,觸發FGCSystem.gc
六、SQL性能優化
數據庫三范式是什么?數據庫的事務、ACID及隔離級別?不考慮事務的隔離性,容易產生哪三種情況?數據庫連接池原理?什么是B-Tree?什么是B+Tree?MySQL數據庫索引結構?什么是索引?什么條件適合建立索引?什么條件不適合建立索引?索引失效的原因有哪些?如何優化避免索引失效?MySQL如何啟動慢查詢日志?MySQL如何使用show Profile進行SQL分析?一條執行慢的SQL如何進行優化,如何通過Explain+SQL分析性能?什么是行鎖、表鎖、讀鎖、寫鎖,說說它們各自的特性?什么情況下行鎖變表鎖?什么情況下會出現間隙鎖?談談你對MySQL的in和exists用法的理解?MySQL的數據庫引擎有哪些,如何確定在項目中要是用的存儲引擎?count(*)、count(列名)和count(1)的區別?union和union all的區別?七、Spring框架
Spring的IOC和AOP機制?Spring中Autowired和Resource關鍵字的區別?依賴注入的方式有幾種,各是什么?Spring容器對Bean組件是如何管理的?Spring容器如何創建?Spring事務分類?Spring事務的傳播特性?Spring事務的隔離級別?Spring的通知類型有哪些?八、SpringMVC框架
SpringMVC完整工作流程,熟讀源碼流程?SpringMVC如何處理JSON數據?SpringMVC攔截器原理,如何自定義攔截器?SpringMVC如何將請求映射定位到方法上面?結合源碼闡述?SpringMVC常見注解有哪些?SpringMVC容器和Spring容器的區別?SpringMVC的控制器是不是單例模式,如果是,有什么問題,怎么解決?九、MyBatis框架
MyBatis中#和$的區別?#{}是占位符,預編譯處理,${}是拼接符,是用來替換字符串的Mybatis在處理#{}的時候,會在預編譯的時候把#{}換成?,調用PreparedStatement的set方法來賦值Mybatis在處理${}的時候,會把${}直接替換成變量的值
MyBatis一級緩存原理以及失效情況?緩存就是將用戶經常查詢到的數據放在緩存中,這樣的話,下次用戶再次去查詢數據就不會去從磁盤上查詢,從緩存中查詢,提高了查詢效率,解決了高並發系統的性能問題一級緩存也叫本地緩存:一級緩存是默認打開的,每個SqlSession實例都擁有一個自己的本地緩存,如果創建一個新的SqlSession實例,則該實例擁有一個新的一級緩存。失效情況:1.SqlSeesion不同 2.SqlSession相同,但查詢條件不同 3.SqlSession對象相同,查詢條件也相同,但兩次查詢之間執行了增刪改操作 4.使用了ClearCache()方法
MyBatis二級緩存的使用?工作機制:一個會話查詢一條數據,這個數據就會被放在當前會話的一級緩存中,如果當前會話關閉了,這個會話對應的一級緩存就沒了。但是我們想要的是,會話關閉了,一級緩存中的數據就會放在二級緩存中,新的會話查詢信息,就會在二級緩沖中獲取內容。作用域在Namespace使用步驟:1.讓Mybatis框架支持二級緩存 2.讓當前的映射文件支持二級緩存 3.讓當前的操作支持二級緩存
MyBatis攔截器原理?Mybatis提供了一種插件(plugin)的功能,雖然叫做插件,但其實這是攔截器功能。Mybatis允許你在已映射語句執行過程中的某一點進行攔截調用,Mybatis允許使用插件來攔截的方法調用包括:Executor,ParameterHandler,ResultSetHandler,StatementHandler比如在使用分頁插件來完成Mybatis分頁 分頁插件的原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然后重寫sql,然后在sql語句添加對應的物理分頁語句和物理分頁參數。
看過MyBatis源碼嗎,請說說它的工作流程?1.加載配置文件2.生成SqlSessionFactory工廠3.使用SqlSessionFactory工廠創建SqlSession對象4.使用SqlSession創建Dao接口的代理對象5.使用代理對象執行方法6.關閉SqlSession,釋放資源
十、Java高級部分
Dubbo負載均衡策略?Dubbo中Zookeeper做注冊中心,如果注冊中心集群都掛掉,發布者和訂閱者之間還能通信么?Dubbo完整的一次調用鏈路介紹?請說說SpringBoot自動裝配原理?有用過SpringCloud嗎,請說說SpringCloud和Dubbo有什么不一樣?什么是WebService,如何基於WebService開發接口?談談項目中分布式事務應用場景?使用Redis如何實現分布式鎖?請談談單點登錄原理?Tomcat如何優化?后台系統怎么防止請求重復提交?Linux常見命令有哪些?請說說什么是Maven的依賴、繼承以及聚合?Git暫存區和工作區的區別?Git如何創建、回退以及撤銷版本?