Java多線程
1、線程池的原理,為什么要創建線程池?
答:1)線程池可以降低創建和銷毀線程時的資源消耗,提高響應速度,提高現成的可管理性。
2)線程池構造參數:
corePoolSize:核心線程數
maximumPoolSize:最大線程數
keepAliveTime:空閑時間
unit:空閑時間單位
workQueue:任務等待隊列。ArrayBlockingQueue(有界);SynchronousQueue(容量為1);LinkedBlockingQueue(無界)
threadFactory:線程工廠
handler:任務拒絕策略。丟棄並拋異常(默認策略);丟棄但不拋異常;丟棄最前面的任務;由調用線程處理該任務
3)幾個參數之間的關系。corePoolSize>workQueue>maximumPoolSize>reject
2、線程的生命周期,什么時候會出現僵死進程;
答:1)new -> runnable -> running -> block -> dead
2)兩個線程相互等待對方釋放鎖時,會出現僵死現象
3、什么是現線程安全,如何實現線程安全;
答:1)多線程並發訪問共享資源時,能保證結果正確
2)可通過阻塞同步(加鎖);非阻塞同步(CAS);避免共享資源(session、threadLocal)
4、java線程池如何合理配置核心線程數?
答:1)獲取CPU核數。Runtime.getRuntime().availableProcessors()
2)分析程序屬於CPU密集型還是IO密集型?
CPU密集型,核心線程數=CPU核數+1。減少花在任務切換上的時間
IO密集型,核心線程數=CPU核心數*2。線程越多,CPU利用率越高
5、synchronized、volatile區別、synchronized鎖粒度、模擬死鎖場景、原子性與可見性;
答: 1)死鎖產生的條件:
互斥條件;環路等待;保持條件;不剝奪條件
2)synchronized鎖粒度:無鎖、偏向鎖、輕量鎖、重量鎖
JVM相關
1、JVM內存模型
答:1)內存划分:堆、棧(java、本地)、方法區、計數器。方法區存放類信息、靜態變量、常量、運行時常量池;堆主要放數組、對象、字符串常量池;棧是方法運行過程的內存模型。
方法區和堆都是線程共享的,棧和計數器是線程數有的。
2)JVM內存模型,和Java虛擬機運行時區域有關;JAVA內存模型是JAVA並發編程有關。
3)JAVA內存模型:主存(變量) -> 本地內存(變量副本) -> CPU(使用)
4)緩存一致性協議:
5)工作內存與主內存交互:
lock(鎖定) -> read(讀取) -> load(載入) -> use(使用) -> assign(賦值) -> store(存儲) -> write(寫入) -> unlock(解鎖)
6)內存屏障(Memory barrier):是一種CPU指令,可以讓CPU在內存訪問上有序,保證屏障之前的指令會先於屏障之后的指令執行,用於控制特定條件下的重排序和內存可見性問題
7)指令重排序:為提高效率,程序在運行時內存實際的訪問順序和程序代碼編寫的訪問順序不一定一致
2、JVM里的有幾種classloader,為什么會有多種?
答:BootstrapClassLoader -> ExtensionClassLoader -> AppClassLoader -> UserDefinedClassLoader
1)BootstrapClassLoader,負責加載<JAVA_HOME>/lib下的class,開發者不可以直接使用
2) ExtensionClassLoader,負責加載<JAVA_HOME>/lib/ext下的class,開發者可以直接使用
3)AppClassLoader,負責加載用戶的class
3、java類加載機制、親委派機制、雙親委派模型的好處?
答:1)類加載的幾個階段:加載、連接(驗證、准備、解析)、初始化、使用、卸載。加載的目的是為了獲取該類的二進制流
2)雙親委派:如果一個類加載器收到一個類加載的請求,會先將該請求委托給父級類加載器去加載,每一層都是如此。只有父類反饋無法完成這個加載請求時(它的搜索范圍內找不到這個類),才會向下委托給子類加載器去加載。
3)雙親委派的好處:自己寫的String.java不會覆蓋系統的String.java,進而保護系統內部代碼。
4、什么情況下我們需要破壞雙親委派模型;
答:1)Tomcat的WebAppClassLoader只會加載自己目錄下的class文件,不會交給父類。因為一個Tomcat可以同時裝載多個webapp,可防止jar包沖突
2)根據類加載機制,當被裝載的類引用了另外一個類的時候,虛擬機就會使用裝載第一個類的類裝載器裝載被引用的類。JDBC的Driver接口定義在JDK中,DriverManager也在JDK中,Driver實現類則在各廠商的實現包中,需要子類去加載。
5、常見的JVM調優方法有哪些?可以具體到調整哪個參數,調成什么值?
答:1)給新生代合理的空間,盡量避免新對象直接進入到老年代
2)大對象進入老年代,減少新生代對大對象的GC。 -XX:PretenureSizeThreshold 設置大對象直接進入老年代的閥值
3)設置對象進入老年代的年齡。-XX:MaxTenuringThreshold:默認值是15
6、什么時候觸發FullGC?什么時候觸發MinorGC(YoungGC)?
答:1)主動調用System.gc()
2) 老年代不足、持久代不足
3) YoungGC出現promotion failure
4)穩定對大小。設置 -Xmx 和 -Xms 一樣的值。
7、JVM垃圾收集算法、垃圾收集器、class文件結構是如何解析的
答:1)垃圾回收算法:
a) 標記-清除算法:分成標記階段(將要回收的做標記)和清除階段(將標記的清除)。優點:簡單易實現。缺點:碎片多,導致大對象空間不足觸發垃圾回收。
b) 標記-整理算法:將內存划分為大小相等的兩塊,標記並復制到另一塊區域。優點:內存利用率高。缺點:空間占用大;如果存活對象很多,復制效率低下。
c) 復制算法:將存活的對象復制到另一個區域
d) 分代收集算法:根據對象生命周期划分為多個區域,新生代(Eden8、Survivor1:1,復制算法)、老年代(標記整理)、永久代。
8、CMS回收機制
答:1)初始標記,只標記與“根”直接關聯的對象,此時會Stop the World
2)並發標記,
3)並發預清理
4)重新標記
5)並發清理
6)重新標記
Java擴展
1、紅黑樹的實現原理和應用場景;
2、NIO是什么?適用於何種場景?
3、Java9比Java8改進了什么;
答:模塊化(rt.jar解散開來)、接口私有方法、HTTP2.0、增強Stream
4、HashMap內部的數據結構是什么?底層是怎么實現的?
答:loadFactory:負載因子,默認0.75,槽位占到此比例時,開始擴容,擴容是對數組擴容,長度增長一倍,將源數組保存的數據進行rehash后,放入新數組中。
節點組成:Entry包含Key,Value,Next,hash值幾個字段
數組+鏈表:數組是HASH槽位,通過Entry的next指向下一個節點,形成鏈表。
https://blog.csdn.net/samniwu/article/details/90550196
5、說說反射的用途及實現,反射是不是很慢,我們在項目中是否要避免使用反射;
答:1)調用對象、調用方法、使用字段等
2)Class.forName("xxxxx.class")方法會比較慢,可將此方法放到for循環外面
3)調用方法前,使用method.setAccessible(true)跳過安全檢查,可提高方法調用效率
6、說說自定義注解的場景及實現;
答:1)運行時,靠反射獲取注解。如在AOP中獲取注解,或在filter中獲取注解
2)應用場景:權限、日志、登錄、緩存
7、Arraylist、LinkedList、Vector的 區別;
答:1)Vector是通過數組實現的,線程同步,只允許一個線程寫數據,效率比ArrayList低
2)ArrayList是通過數組實現的,線程異步,適合隨機訪問,不適合頻繁插入、刪除元素
3)LinkedList是通過鏈表實現,適合頻繁插入、刪除場景,但隨機訪問效率低
Spring
1、Spring AOP的實現原理和場景;(應用場景很重要)
2、Spring bean的作用域和生命周期;
3、Spring Boot比Spring做了哪些改進?Spring 5比Spring4做了哪些改進;(慚愧呀,我們還在用Spring4,高版本的沒關心過)
4、Spring IOC是什么?優點是什么?
5、SpringMVC、動態代理、反射、AOP原理、事務隔離級別;
中間件
1、Dubbo完整的一次調用鏈路介紹;
答:1)調用方封裝dubbo協議,包含請求頭和請求體
2)調用方發起調用請求,交給InvokerInvocationHandler調用,最終通過netty的NioClientSocketChannel發送數據
3)服務方將請求解碼
4)服務方將請求內容傳遞給NettyHandler,通過線程池中獲取線程,進入服務調用邏輯
5)服務方返回調用結果,並對響應體進行編碼
6)調用方接收響應結果,解碼響應
2、Dubbo支持幾種負載均衡策略?
答:1)隨機策略
2)輪詢策略
3)最少活躍調用數。耗時短的,被調用次數就多
4)一致Hash
3、Dubbo Provider服務提供者要控制執行並發請求上限,具體怎么做?
答:1)服務端控制。 <dubbo:service interface="com.foo.BarService" executes="10" />
2)客戶端控制。<dubbo:reference interface="com.foo.BarService" actives="10" />
4、Dubbo啟動的時候支持幾種配置方式?
答:1)xml
2)注解
3)javaBean
4)properties文件
5、了解幾種消息中間件產品?各產品的優缺點介紹;
答:1)Rabbit 集群不支持動態擴展,erlang語言編寫,不利於源碼查看
2)ActiveMQ 莫名其妙丟消息,后期維護較少,不適用於上千個隊列的場景
3)RocketMQ 性能好,簡單;新文檔較少
4)Kafka 適用於日志領域
6、消息中間件如何保證消息的一致性和如何進行消息的重試機制?
https://my.oschina.net/floor/blog/1587537
答:1)生產者發送消息前,保證生產者本地的邏輯已經處理完成
2)消費者確認消息機制:自動確認、手動確認、無確認可被多次消費
3)一致性問題原因:生產者發送消息后,消費者接收到消息會自動確認,此時消費者掛掉了。此時就會存在生產者已處理、消費者未處理的不一致的問題。
4)如何處理消息不一致的問題?
a) 生產者再發一次消息。通過一張表來記錄每個消息的發送狀態,未處理完成的消息,會定時再發送(定時補償)。消費者通過分布式鎖,來保證消息不被重復消費
b) 消息者主動查詢生產者消息是否結束
7、Spring Cloud 熔斷、限流、降級;
答:1)降級。(可以在客戶端[主動降級],也可在服務端[被動])
a) 降級處理策略:失敗重連;直接返回友好提示;調用備用服務;返回緩存數據。
b) 降級回退方式:FailFast(快速失敗);FailSilent(無聲失敗);......
2)限流。可放入網關中,通過過濾器實現。向令牌桶以恆定速度添加令牌,一個請求消耗一個令牌。令牌桶中的令牌數量大於0才可以訪問,否則拒絕
3)熔斷。熔斷不等於宕機!熔斷時,服務器還是有響應能力的,只是響應慢或暫無響應。
https://blog.csdn.net/loushuiyifan/article/details/82702522
https://www.jianshu.com/p/b9af028efebb hystrix單獨使用
數據庫篇
1、鎖機制介紹:行鎖、表鎖、排他鎖、共享鎖;
答:1)表級鎖:開銷小,加鎖快;不會出現死鎖;粒度大,發生鎖沖突的概率最高,並發度最低。
2)頁級鎖:介於表級鎖和行級鎖之間
3)行級鎖:開銷大,加鎖慢;容易出現死鎖;粒度小,發生鎖沖突的概率最低,並發度最高。
https://blog.csdn.net/waS_TransvolnoS/article/details/101146344
2、樂觀鎖的業務場景及實現方式
3、事務介紹,分布式事物的理解,常見的解決方案有哪些,什么事兩階段提交、三階段提交;
4、MySQL記錄binlog的方式主要包括三種模式?每種模式的優缺點是什么?
5、MySQL鎖,悲觀鎖、樂觀鎖、排它鎖、共享鎖、表級鎖、行級鎖;
6、分布式事務的原理2階段提交,同步\異步\阻塞\非阻塞;
7、數據庫事務隔離級別,MySQL默認的隔離級別、Spring如何實現事務、
8、JDBC如何實現事務、嵌套事務實現、分布式事務實現;
9、SQL的整個解析、執行過程原理、SQL行轉列;
Redis
1、Redis為什么這么快?redis采用多線程會有哪些問題?
2、Redis支持哪幾種數據結構;
3、Redis跳躍表的問題;
4、Redis單進程單線程的Redis如何能夠高並發?
5、Redis如何使用Redis實現分布式鎖?
6、Redis分布式鎖操作的原子性,Redis內部是如何實現的?
Tomcat
1、Tomcat類加載機制
答:1)Tomcat不遵循雙親委派模型;
2)隔離性。同一個Tomcat可同時裝載不同版本的jar包,互不影響
2、Tomcat架構
答:Server >> Service >> *Connector & Container >> Host/Engine/Context
技術四面面試題如下
一面(問了數據結構、jvm、鎖等):
HashMap底層如何實現?
Hash一致算法?
說說HashMap和ConcurrentHashMap的區別?treemap和HashMap的區別?
java的內存分區?
java對象的回收方式,回收算法?
CMS和G1了解嗎?
CMS解決什么問題,說一下回收的過程?
CMS回收停頓了幾次?
java棧什么時候會內存溢出,java堆呢,說一種場景?
集合類如何解決這個問題(軟引用和弱引用),講下這個兩個引用的區別?
java里的鎖了解哪些?
synchronized鎖升級的過程(偏向鎖到輕量鎖再到重量級鎖),分別如何實現的,解決的是哪些問題?
Tomcat的基本架構是什么?
什么是類加載器?
說說雙親委派模型機制?
GC的機制是什么?GC算法和回收策略?
二面(線程、數據庫、緩存、協議等):
線程池由哪些組件組成?
有哪些線程池,分別怎么使用?拒絕策略有哪些?
什么時候多線程會發生死鎖,寫一個例子?
Redis的數據結構是什么?線程模型說一下?
講講Redis的數據淘汰機制?
說說Redis的數據一致性問題?
Redis的分布式怎么做?
RPC講一下?
三次握手和四次揮手?如果沒有三次握手有問題嗎?
Http請求過程,DNS解析的過程?
InnoDB支持的四種事務隔離級別名稱是什么?有什么區別?說說MySQL隔離級別?
事務的特性及慢查詢?
BTree機制說一下?
說說MySQL常用的優化方法?
三面(分布式,消息隊列等):
cap了解嗎,分別指什么?
強一致性和弱一致性有什么方法來實現的?
負載均衡怎么實現?為什么這么做?
緩存雪崩說下?
MySQL主從復制怎么實現的?具體原理是什么?有什么優缺點?
講講分布式事務?
消息隊列,用到什么場景(削峰,限流,異步)?
zk的性能瓶頸怎么克服?
講了下kafka,怎么保證數據不丟失?確保消息不會重復消費?
消息送達確認是怎么實現的?