網(wǎng)站LOGO透明底色PNG格式怎么做的最新足球賽事
文章目錄
- java 基礎(chǔ)
- 1、JDK 和 JRE的區(qū)別
- 2、= = 和equals的區(qū)別
- 3、String、StringBuffer、StringBuilder
- 4、String str = “a”、 new String(“a”)一樣嗎?
- 5、ArrayList 和 LinkedList的區(qū)別?
- 6、HashMap的原理與實(shí)現(xiàn)
- 6.1、容量與擴(kuò)容
- 6.2、擴(kuò)容機(jī)制
- 7、HashMap中的put方法執(zhí)行過程
- 8、ConcurrentHashMap工作原理
- 9、SimpleDateFormat是線程安全的嗎?
- 10、java.util.Date 與 java.sql.Date 有什么區(qū)別?
- 11、對(duì)象被置為null,垃圾回收器會(huì)立即釋放占用的內(nèi)存嗎?
- 12、java的數(shù)據(jù)結(jié)構(gòu)有哪些
- 13、java中異常分為幾種
- 14、Error與Exception的區(qū)別
- 15、java的單模式
- 16、哪些集合是線程安全的?
- 17、synchronized原理
- 18、volatile有什么用
- 19、synchronized關(guān)鍵字可以實(shí)現(xiàn)什么類型的鎖?
- 20、怎么創(chuàng)建不可修改的集合
- 21、sleep和wait的區(qū)別
- 22、jvm內(nèi)存結(jié)構(gòu)
- 23、運(yùn)行時(shí)數(shù)據(jù)區(qū)
- 24、堆結(jié)構(gòu)(jdk1.8)
- 25、java垃圾回收算法
- 26、垃圾回收器
- 27、GC Roots 可以是哪些?
- 28、引用類型有哪些
- 29、java的IO流分為幾種?
- 30、BIO、NIO、AIO
- 31、NIO直接緩沖區(qū)與非直接緩沖區(qū)
- 32、NIO內(nèi)存映射到緩存
- 33、序列化和反序列化
- 網(wǎng)絡(luò)基礎(chǔ)
- 1、TCP 三次握手
- 2、TCP 四次揮手關(guān)閉連接
- 3、TCP與UDP的區(qū)別
- 4、請(qǐng)求出現(xiàn)503是什么問題
- spring
- 1、spring boot啟動(dòng)流程
- 2、spring bean的實(shí)例化
- 3、Spring的ioc
- 4、Spring的aop
- 5、Spring的類加載機(jī)制
- 6、Java類加載機(jī)制
- 7、雙親委派模型
- 8、Spring怎么解決循環(huán)依賴
- 9、Spring 用到了哪些設(shè)計(jì)模式?
- 10、設(shè)計(jì)模式的六大原則
- 11、spring的事務(wù)和分布式事務(wù)
- 12、分布式事務(wù)的實(shí)現(xiàn)方式
- 13、分布式鎖?
- mysql
- 1、事務(wù)四大特性
- 2、事務(wù)的隔離級(jí)別
- 3、臟讀、重復(fù)讀、幻讀
- 4、B樹和B+樹的區(qū)別
- 5、mysql為什么用B+樹
- 6、mysql鎖有哪些
- 7、mysql的redolog、binlog、undolog
- 8、mysql二階段提交
- 9、mysql什么時(shí)候會(huì)索引失效
- redis
- 1、緩存雪崩、緩存擊穿、緩存穿透
- 2、會(huì)員中有大量要過期怎么處理
- 多線程
- 1、線程同步的方法
- 2、什么是ThreadLocal,以及其實(shí)現(xiàn)原理?
- 3、為什么要使用線程池
- 4、線程池執(zhí)行過程
- 5、線程池的創(chuàng)建方式
- 6、線程池的7個(gè)參數(shù)
- 7、線程池隊(duì)列有哪些
- 8、線程池拒絕策略有哪些
- 9、線程池的關(guān)閉
- 10、使用無界隊(duì)列的線程池會(huì)導(dǎo)致內(nèi)存飆升嗎?
- 11、線程創(chuàng)建的幾種方式
- 12、Future有什么用
- 13、FutureTask有什么用
- 14、線程的生命周期(狀態(tài))
- 15、 i++是線程安全的嗎
- 16、可重入鎖ReentrantLock
- 16.1、Synchronized和ReentrantLock的相同
- 16.2、Synchronized和ReentrantLock的不同
- 17、synchronized可重入鎖的實(shí)現(xiàn)原理
- Activiti流程引擎
- 1、Activiti工作流的主要組件
- 2、Activiti工作流有什么優(yōu)勢(shì)
- 3、Activiti工作流service有哪些
- 4、流程實(shí)例和執(zhí)行對(duì)象的區(qū)別
- 5、工作流中一個(gè)任務(wù)完成后,存在多條連線,如何處理
- 6、Activiti工作流中排他網(wǎng)關(guān)和并行網(wǎng)關(guān)都能執(zhí)行什么功能
- 7、分配個(gè)人任務(wù)的三種方式
- 8、個(gè)人任務(wù)和組任務(wù)的查詢一樣嗎?
- 綜合性問題
- 1、生產(chǎn)環(huán)境發(fā)生內(nèi)存泄露怎么排查問題?
java 基礎(chǔ)
1、JDK 和 JRE的區(qū)別
2、= = 和equals的區(qū)別
= = 比基本類型:比較值,
= = 比引用類型:比較引用。
equals本質(zhì)上就是= =,String、integer等重寫了equals方法,把它變成了值比較。
3、String、StringBuffer、StringBuilder
String 每次操作都會(huì)生成新的String對(duì)象
StringBuffer 線程安全的,所有公開方法都是 synchronized 修飾的
StringBuilder 非線程安全的,性能更高一些
4、String str = “a”、 new String(“a”)一樣嗎?
前者會(huì)放到常量池,后者放到堆內(nèi)存
5、ArrayList 和 LinkedList的區(qū)別?
ArraList 是基于數(shù)組實(shí)現(xiàn)的線性表,尾部插入和數(shù)據(jù)訪問效率高
LinkedList是雙向鏈表,中間插入和頭部插入效率高,查詢效率低
6、HashMap的原理與實(shí)現(xiàn)
- 數(shù)組:HashMap底層由一個(gè)數(shù)組組成,數(shù)組的每個(gè)元素稱為一個(gè)桶(存一個(gè)或多個(gè)Entry)。
- 鏈表:多個(gè)鍵值對(duì)映射到同一個(gè)桶,會(huì)發(fā)生哈希沖突。哈希沖突后使用鏈表將沖突的鍵值對(duì)連接起來。這就是所謂的“數(shù)組 + 鏈表”的散列數(shù)據(jù)結(jié)構(gòu)。
- 紅黑樹:Java 1.8 開始,當(dāng)鏈表的長(zhǎng)度超過一定閾值(默認(rèn)為 8)時(shí),鏈表會(huì)轉(zhuǎn)換為紅黑樹。紅黑樹是一種自平衡的二叉查找樹,能夠提高 HashMap 的查詢效率。
6.1、容量與擴(kuò)容
HashMap 的默認(rèn)大小是16(16是為了確保算出來的值足夠隨機(jī)),
當(dāng)容量到達(dá)閾值的時(shí)候會(huì)觸發(fā)擴(kuò)容,閾值=容量加載因子,160.75=12。
每次擴(kuò)容是之前容量的2倍。
6.2、擴(kuò)容機(jī)制
JDK 1.7:空參構(gòu)造函數(shù),內(nèi)部是空數(shù)組,第一次put初始化數(shù)組。
JDK1.8 : 空參構(gòu)造函數(shù),內(nèi)部是null,第一次put初始化數(shù)組。
7、HashMap中的put方法執(zhí)行過程
1、判斷鍵值對(duì)數(shù)組是否為空(null)或者length=0,是的話就執(zhí)行resize()方法進(jìn)行擴(kuò)容。
2、不是就根據(jù)鍵值key計(jì)算hash值得到插入的數(shù)組索引i。
3、判斷索引i這個(gè)位置是否是null,如果是,就新建節(jié)點(diǎn)。如果不是,判斷首個(gè)元素是否和key一樣,一樣就直接覆蓋。
4、如果位置I的首個(gè)元素和key不一樣,判斷是否是紅黑樹,如果是紅黑樹,直接在樹中插入鍵值對(duì)。
5、如果不是紅黑樹,開始遍歷鏈表,判斷鏈表長(zhǎng)度是否大于8,如果大于8就轉(zhuǎn)成紅黑樹,在樹中執(zhí)行插入操作,如果不是大于8,就在鏈表中執(zhí)行插入;在遍歷過程中判斷key是否存在,存在就直接覆蓋對(duì)應(yīng)的value值。
6、插入成功后,就需要判斷實(shí)際存在的鍵值對(duì)數(shù)量size是否超過了最大容量threshold,如果超過了,執(zhí)行resize方法進(jìn)行擴(kuò)容。
8、ConcurrentHashMap工作原理
Jdk1.7
JDK1.8
JDK1.7,結(jié)構(gòu)為segment+數(shù)組+鏈表,通過繼承 ReentrantLock加分段鎖。每次需要加鎖的操作鎖住的是一個(gè) segment,這樣只要保證每個(gè) Segment 是線程安全的。
JDK1.8,放棄了鎖分段的概念,使用Node+CAS+Synchronized的方式實(shí)現(xiàn)并發(fā),的結(jié)構(gòu)為數(shù)組+鏈表+紅黑樹
9、SimpleDateFormat是線程安全的嗎?
DateFormat的所有實(shí)現(xiàn)都是線程不安全的。
10、java.util.Date 與 java.sql.Date 有什么區(qū)別?
java.util.Date表示一個(gè)日期和時(shí)間,通常用于表示一個(gè)時(shí)間戳。
java.sql.Date是java.util.Date的子類,它只表示日期,不包含時(shí)間。
11、對(duì)象被置為null,垃圾回收器會(huì)立即釋放占用的內(nèi)存嗎?
不會(huì),這個(gè)對(duì)象可能被回收
12、java的數(shù)據(jù)結(jié)構(gòu)有哪些
線性表、鏈表、棧、隊(duì)列、map、樹
13、java中異常分為幾種
編譯時(shí)異常、運(yùn)行時(shí)異常
編譯時(shí)異常:空指針異常、數(shù)值轉(zhuǎn)換異常、數(shù)組越界異常等
14、Error與Exception的區(qū)別
- Error和Exception都繼承了Throwable類 。
異常可以通過程序捕捉。 - Error是系統(tǒng)錯(cuò)誤,通常比較嚴(yán)重。
15、java的單模式
餓漢式:默認(rèn)創(chuàng)建對(duì)象
懶漢式:第一次使用時(shí)創(chuàng)建對(duì)象
餓漢式:1、靜態(tài)變量,2、靜態(tài)代碼塊
懶漢式:3、靜態(tài)變量(初始化方法加載),4、同步方法,5、同步代碼塊
6、雙重檢查
7、靜態(tài)內(nèi)部類(利用jvm對(duì)靜態(tài)內(nèi)部類在使用時(shí)加載的機(jī)制)
8、枚舉
16、哪些集合是線程安全的?
1、Vector (vector比arraylist多個(gè)synchronized同步,因此系統(tǒng)開銷比arraylist大)
2、hashTable
3、ConcurrentHashMap
17、synchronized原理
synchronized主要有三種使用方式:修飾普通同步方法、修飾靜態(tài)同步方法、修飾同步方法塊。
鎖的升級(jí)過程:
1、無鎖,不鎖住資源,多個(gè)線程只有一個(gè)能修改資源成功,其他線程會(huì)重試;
2、偏向鎖,同一個(gè)線程獲取同步資源時(shí),沒有別人競(jìng)爭(zhēng)時(shí),去掉所有同步操作,相當(dāng)于沒鎖;
3、輕量級(jí)鎖,多個(gè)線程搶奪同步資源時(shí),沒有獲得鎖的線程使用CAS自旋等待鎖的釋放;
4、重量級(jí)鎖,多個(gè)線程搶奪同步資源時(shí),使用操作系統(tǒng)的互斥量進(jìn)行同步,沒有獲得鎖的線程阻塞等待喚醒
synchronized關(guān)鍵字三大特性:
原子性(指令不可分割)、
可見性(其他線程可看見修改)、
有序性(代碼是順序執(zhí)行)
volatile關(guān)鍵字只能保證可見性和有序性,不能保證原子性,也稱為是輕量級(jí)的synchronized。
18、volatile有什么用
- 可見性:當(dāng)一個(gè)線程修改了 volatile 變量的值,其他線程能夠立即看到修改后的值。
(這是因?yàn)?volatile 變量的讀寫操作不會(huì)被緩存在寄存器或其他處理器內(nèi)部的緩存中,而是直接從內(nèi)存中讀取或?qū)懭?。因?#xff0c;使用 volatile 變量可以確保多線程之間的數(shù)據(jù)同步。) - 禁止指令重排序:編譯器或處理器可能會(huì)對(duì)代碼進(jìn)行優(yōu)化,對(duì)指令進(jìn)行重新排序,以提高執(zhí)行效率。volatile 變量的讀寫操作不會(huì)被重排序,這樣可以確保指令按照代碼中的順序執(zhí)行,避免了因指令重排序?qū)е碌臄?shù)據(jù)不一致問題。
- 原子性:volatile 變量在讀寫操作時(shí),具有原子性。這意味著,多個(gè)線程同時(shí)訪問 volatile 變量時(shí),不會(huì)發(fā)生沖突。雖然 volatile 變量不保證復(fù)合操作的原子性(如自增或復(fù)合賦值操作),但簡(jiǎn)單的讀寫操作具有原子性。
19、synchronized關(guān)鍵字可以實(shí)現(xiàn)什么類型的鎖?
悲觀鎖:每次訪問共享資源時(shí)都會(huì)上鎖。
非公平鎖:線程獲取鎖的順序并不一定是按照線程阻塞的順序。
可重入鎖:已經(jīng)獲取鎖的線程可以再次獲取鎖。
獨(dú)占鎖或者排他鎖:該鎖只能被一個(gè)線程所持有,其他線程均被阻塞
20、怎么創(chuàng)建不可修改的集合
List<String> list = new ArrayList<>();list.add("1");Collection<String> listC = Collections.unmodifiableCollection(list); // listC不可修改listC.add("2"); // listC 報(bào)錯(cuò)
21、sleep和wait的區(qū)別
- Sleep是線程內(nèi)停頓,不釋放鎖,自動(dòng)喚醒,sleep 是 Thread 類的靜態(tài)本地方法,
- Wait要釋放鎖,必須放在 synchronized 塊里面,需要 notify/ notifyAll 進(jìn)行喚醒,wait 是 Object 類的本地方法。Wait可能還是有機(jī)會(huì)重新競(jìng)爭(zhēng)到鎖繼續(xù)執(zhí)行的。
22、jvm內(nèi)存結(jié)構(gòu)
1、程序計(jì)數(shù)器:指向當(dāng)前線程正在執(zhí)行的字節(jié)碼指令的行號(hào)。
2、本地方法棧:Native方法。
3、棧(虛擬機(jī)棧):每個(gè)Java方法在被調(diào)用的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀,用來存儲(chǔ)局部變量表(八大原始類型、封裝類型)、作數(shù)棧、動(dòng)態(tài)鏈接、方法出口。
4、堆:對(duì)象實(shí)例、數(shù)組
5、方法區(qū):各個(gè)線程共享的內(nèi)存區(qū)域,存儲(chǔ)類的結(jié)構(gòu)信息,例如運(yùn)行時(shí)常量池,字段(通過引用常量池中的常量來描述)和方法等數(shù)據(jù),以及方法和構(gòu)造函數(shù)的代碼,包括用于類和實(shí)例初始化以及接口初始化的特殊方法。
23、運(yùn)行時(shí)數(shù)據(jù)區(qū)
24、堆結(jié)構(gòu)(jdk1.8)
25、java垃圾回收算法
-
標(biāo)記-清除算法:
1、標(biāo)記,從根節(jié)點(diǎn)出發(fā)遍歷對(duì)象,對(duì)訪問過的對(duì)象打上標(biāo)記
2、清除,對(duì)沒有標(biāo)記的對(duì)象進(jìn)行回收 -
標(biāo)記-整理算法:
1、標(biāo)記,從根節(jié)點(diǎn)出發(fā)遍歷對(duì)象,對(duì)訪問過的對(duì)象打上標(biāo)記
2、讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存 -
復(fù)制算法:用在新生代,把可用的對(duì)象從一個(gè)地方拷貝到另一個(gè)地方
-
三色標(biāo)記法:CMS、G1垃圾回收器都使用了三色標(biāo)記法。
白色:沒有標(biāo)記的對(duì)象(垃圾對(duì)象)
灰色:該對(duì)象已標(biāo)記,對(duì)象下的屬性還沒全被標(biāo)記
黑色:該對(duì)象已標(biāo)記,對(duì)象下的屬性也全被標(biāo)記 -
分代回收算法:堆空間分為新生代和老年代
Minor GC : 新生代回收
Major GC : 老年代回收,出現(xiàn)了 Major GC,經(jīng)常會(huì)伴隨至少一次的 Minor GC。
Full GC : 新生代 + 老年代回收 -
可達(dá)性分析算法:以GC Roots為起始點(diǎn),從上至下的方式搜索被根對(duì)象集合所連接的目標(biāo)對(duì)象是否可達(dá)。內(nèi)存中的存活對(duì)象都會(huì)被根對(duì)象集合直接或間接連接著,搜索所走過的路徑稱為引用鏈。
26、垃圾回收器
JDK1到JDK13的發(fā)展歷程中,一共出現(xiàn)了10種垃圾回收器
- Serial(串行收集器):新生代,只使用一條GC線程進(jìn)行垃圾回收,過程中暫停其他工作線程。
- Parallel Scavenge(并行收集器):新生代,復(fù)制算法實(shí)現(xiàn),并行多線程回收器,常用于新生代。
- CMS :老年代,標(biāo)記-清除算法實(shí)現(xiàn)(最后會(huì)產(chǎn)生許多內(nèi)存碎片,到達(dá)一定量時(shí),交由串行收集器處理)。
- G1 :主要作用于老年代,標(biāo)記-整理算法實(shí)現(xiàn)。
各個(gè)收集器的Full GC:
27、GC Roots 可以是哪些?
棧中引用的對(duì)象、本地方法棧內(nèi)引用的對(duì)象、靜態(tài)屬性引用的對(duì)象、常量引用的對(duì)象、同步鎖 synchronized 持有的對(duì)象、虛擬機(jī)內(nèi)部的引用、反映 java 虛擬機(jī)內(nèi)部情況的 JMXBean、JVMTI 中注冊(cè)的回調(diào)、本地代碼緩存等
28、引用類型有哪些
強(qiáng)引用:new出來的對(duì)象就是強(qiáng)引用,垃圾回收器不會(huì)回收
軟引用:new SoftReference(),內(nèi)存不足時(shí)回收
弱引用:第一次GC回收時(shí),掃到了回收。ThreadLocal的map的key是弱引用
虛引用:虛引用主要用來跟蹤對(duì)象的回收,清理被銷毀對(duì)象的相關(guān)資源。
29、java的IO流分為幾種?
按功能分:輸入流、輸出流
按類型分:字節(jié)流(8個(gè)字節(jié)為單位)、字符流(16)
30、BIO、NIO、AIO
BIO:同步阻塞IO,使用簡(jiǎn)單,并發(fā)處理能力低
NIO:同步非阻塞IO,通過channel實(shí)現(xiàn)多路復(fù)用
AIO:異步非阻塞IO,基于事件和回調(diào)機(jī)制
31、NIO直接緩沖區(qū)與非直接緩沖區(qū)
- 緩沖區(qū)分配方式:
非直接緩沖區(qū):通過allocate()方法分配緩沖區(qū),將緩沖區(qū)建立在 JVM 的內(nèi)存中。
直接緩沖區(qū):通過allocateDirect()方法分配直接緩沖區(qū),將緩沖區(qū)建立在物理內(nèi)存中。 - 數(shù)據(jù)傳輸效率:
非直接緩沖區(qū):在操作系統(tǒng)和 JVM 之間進(jìn)行數(shù)據(jù)傳輸,可能涉及到內(nèi)存復(fù)制操作,因此相對(duì)較慢。
直接緩沖區(qū):由于直接建立在物理內(nèi)存中,可以減少內(nèi)存復(fù)制操作,提高數(shù)據(jù)傳輸效率。
32、NIO內(nèi)存映射到緩存
將文件或文件的一部分映射到內(nèi)存中的技術(shù)。通過內(nèi)存映射文件,可以以字節(jié)數(shù)組的方式訪問文件內(nèi)容,而無需進(jìn)行昂貴的系統(tǒng)調(diào)用。
33、序列化和反序列化
把當(dāng)前jvm進(jìn)程中的對(duì)象,傳輸?shù)搅硪粋€(gè)進(jìn)程里面進(jìn)行恢復(fù)。序列化后進(jìn)行傳輸,恢復(fù)就是反序列化。
常用的序列化工具json、xml、kyro、hessian等
網(wǎng)絡(luò)基礎(chǔ)
1、TCP 三次握手
1、客戶端請(qǐng)求建立連接
2、服務(wù)端應(yīng)答,并請(qǐng)求建立連接
3、客戶端確認(rèn)客戶端應(yīng)答
2、TCP 四次揮手關(guān)閉連接
1、客戶端請(qǐng)求斷開連接
2、服務(wù)端確認(rèn)應(yīng)答
3、服務(wù)端請(qǐng)求斷開連接
4、客戶端確認(rèn)應(yīng)答
3、TCP與UDP的區(qū)別
- TCP:面向連接的協(xié)議,一個(gè)TCP連接必須要經(jīng)過三次“對(duì)話”才能建立起來。TCP保證數(shù)據(jù)正確性、數(shù)據(jù)順序,
- UDP:一個(gè)非連接的協(xié)議,傳輸數(shù)據(jù)之前源端和終端不建立連接。UDP可能丟包、不保證順序;
4、請(qǐng)求出現(xiàn)503是什么問題
503 錯(cuò)誤是 HTTP 協(xié)議中的一種服務(wù)器錯(cuò)誤,表示服務(wù)器暫時(shí)無法處理請(qǐng)求。這個(gè)錯(cuò)誤通常發(fā)生在服務(wù)器維護(hù)、過載或者遇到了意外的問題時(shí)。
- 1、確認(rèn)問題:首先,確認(rèn)問題是否存在??梢酝ㄟ^監(jiān)控系統(tǒng)、日志或者與前端開發(fā)人員溝通來了解是否存在 503 錯(cuò)誤。
- 2、分析錯(cuò)誤原因:一旦確認(rèn)存在 503 錯(cuò)誤,需要分析錯(cuò)誤的原因。這可能包括服務(wù)器過載、硬件故障、軟件錯(cuò)誤、配置問題等。
- 3、制定解決方案:根據(jù)錯(cuò)誤原因,制定相應(yīng)的解決方案。以下是一些建議:
如果是服務(wù)器過載,可以考慮增加服務(wù)器數(shù)量、優(yōu)化數(shù)據(jù)庫查詢、限制并發(fā)連接數(shù)等。
如果是硬件故障,及時(shí)更換硬件或升級(jí)服務(wù)器。
如果是軟件錯(cuò)誤或配置問題,修復(fù)代碼或配置錯(cuò)誤。
考慮使用負(fù)載均衡器分發(fā)請(qǐng)求,以避免單個(gè)服務(wù)器過載。
優(yōu)化代碼,減少不必要的資源消耗。 - 4、實(shí)施解決方案:根據(jù)解決方案,修改代碼、配置服務(wù)器或其他相關(guān)組件。
測(cè)試驗(yàn)證:在實(shí)施解決方案后,需要對(duì)系統(tǒng)進(jìn)行測(cè)試,確保 503 錯(cuò)誤已得到解決,并且不會(huì)影響其他請(qǐng)求的正常處理。 - 5、預(yù)防措施:為防止 503 錯(cuò)誤再次發(fā)生,可以采取以下措施:定期檢查、監(jiān)控系統(tǒng)、制定應(yīng)急預(yù)案,以應(yīng)對(duì)突發(fā)情況。
spring
1、spring boot啟動(dòng)流程
1、首先從main找到run方法,在執(zhí)行run之前new一個(gè)springApplication對(duì)象
2、進(jìn)入run方法,創(chuàng)建應(yīng)用監(jiān)聽器
3、加載配置文件
4、加載應(yīng)用上下文,當(dāng)作run方法的返回對(duì)象
5、創(chuàng)建spring容器,實(shí)現(xiàn)自動(dòng)配置和bean的實(shí)例化
2、spring bean的實(shí)例化
兩個(gè)階段:容器啟動(dòng)階段、bean實(shí)例化階段
容器啟動(dòng)階段:加載元數(shù)據(jù)、對(duì)各種處理器進(jìn)行注冊(cè)、上下文初始化、事件廣播初始化
Bean實(shí)例化:
1、加載Bean定義:spring從配置文件或注解中加載bean定義
2、實(shí)例化Bean: 根據(jù)bean的定義,創(chuàng)建bean實(shí)例。如果bean定義中指定了初始化方法,spring會(huì)在實(shí)例化后調(diào)用這些方法。
3、屬性賦值:如果bean中定義了屬性,spring會(huì)使用屬性值或構(gòu)造器參數(shù)對(duì)屬性進(jìn)行賦值。
4、Bean注冊(cè):將Bean實(shí)例注冊(cè)到Spring容器中,以便在其他地方使用。
3、Spring的ioc
ioc中文名控制反轉(zhuǎn)(另一名稱DI依賴注入)。IOC是指,利用反射的原理將創(chuàng)建對(duì)象的權(quán)利交給Spring容器,spring在運(yùn)行的時(shí)候根據(jù)配置文件來動(dòng)態(tài)的創(chuàng)建對(duì)象和維護(hù)對(duì)象之間的關(guān)系,實(shí)現(xiàn)了松耦合的思想。
4、Spring的aop
面向切行期間,不修改源碼對(duì)已有方法進(jìn)行增強(qiáng)。
配置方式:基于注解配置aop、基于XML的Aop、編程式創(chuàng)建代理
- AOP有哪些實(shí)現(xiàn)方式?
AOP有兩種實(shí)現(xiàn)方式:靜態(tài)代理(編譯時(shí)增強(qiáng))和動(dòng)態(tài)代理(運(yùn)行時(shí)創(chuàng)建)。 - 動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式?
JDK動(dòng)態(tài)代理:通過接口實(shí)現(xiàn),代理類根據(jù)目標(biāo)類實(shí)現(xiàn)的接口動(dòng)態(tài)生成,不需要自己編寫
CGLIB動(dòng)態(tài)代理:通過繼承實(shí)現(xiàn)。
5、Spring的類加載機(jī)制
Springboot中的類SPI擴(kuò)展機(jī)制
在springboot的自動(dòng)裝配過程中,最終會(huì)加載META-INF/spring.factories文件,而加載的過程是由SpringFactoriesLoader加載的。從CLASSPATH下的每個(gè)Jar包中搜尋所有META-INF/spring.factories配置文件,然后將解析properties文件,找到指定名稱的配置后返回。需要注意的是,其實(shí)這里不僅僅是會(huì)去ClassPath路徑下查找,會(huì)掃描所有路徑下的Jar包,只不過這個(gè)文件只會(huì)在Classpath下的jar包中。
6、Java類加載機(jī)制
jvm的類加載器默認(rèn)使用的是雙親委派模式。三種默認(rèn)的類加載器 啟動(dòng)類加載器、擴(kuò)展類加載器、應(yīng)用程序類加載器。每一個(gè)中類加載器都確定了從哪一些位置加載文件。也可以通過繼承java.lang.classloader實(shí)現(xiàn)自己的類加載器。
7、雙親委派模型
當(dāng)一個(gè)類加載器收到類加載任務(wù)時(shí),會(huì)先交給自己的父加載器去完成,因此最終加載任務(wù)都會(huì)傳遞到最頂層的啟動(dòng)類加載器,只有當(dāng)父加載器無法完成加載任務(wù)時(shí),才會(huì)嘗試自己來加載。
8、Spring怎么解決循環(huán)依賴
A依賴于B,B依賴于C,C又依賴于A
解決辦法:
1、Spring首先從一級(jí)緩存“SingletonObjects”中獲取。
2、獲取不到并且對(duì)象正在創(chuàng)建中,就再從二級(jí)緩存“earlySingletonObjects”中獲取。
3、如果還是獲取不到且允許singletonFactories通過getObject()獲取,就從三級(jí)緩存singletonFactory.getObject()(三級(jí)緩存)獲取。
4、如果從三級(jí)緩存中獲取到就從singletonFactories中移除,并放入earlySingletonObjects中。其實(shí)也就是從三級(jí)緩存移動(dòng)到了二級(jí)緩存。
無法解決的循環(huán)依賴:A依賴于B,B依賴于A
9、Spring 用到了哪些設(shè)計(jì)模式?
- 工廠模式:spring在使用getBean()調(diào)用獲得該bean時(shí),會(huì)自動(dòng)調(diào)用該bean的getObject()方法。每個(gè) Bean 都會(huì)對(duì)應(yīng)一個(gè) FactoryBean,如 SqlSessionFactory 對(duì)應(yīng) SqlSessionFactoryBean。
- 單例模式:一個(gè)類僅有一個(gè)實(shí)例,提供一個(gè)訪問它的全局訪問點(diǎn)。
- 適配器模式:Spring提供了一個(gè)適配器接口,每一種 Controller 對(duì)應(yīng)一種 HandlerAdapter 實(shí)現(xiàn)類,當(dāng)請(qǐng)求過來,SpringMVC會(huì)調(diào)用getHandler()獲取相應(yīng)的Controller,然后獲取該Controller對(duì)應(yīng)的 HandlerAdapter,最后調(diào)用HandlerAdapter的handle()方法處理請(qǐng)求,實(shí)際上調(diào)用的是Controller的handleRequest()。每次添加新的 Controller 時(shí),只需要增加一個(gè)適配器類就可以,無需修改原有的邏輯。
- 代理模式:spring 的 aop 使用了動(dòng)態(tài)代理,有兩種方式Jdk動(dòng)態(tài)代理和Cglib動(dòng)態(tài)代理。
- 模板模式:Spring 中 jdbcTemplate、hibernateTemplate 等,就使用到了模板模式。
10、設(shè)計(jì)模式的六大原則
- 開閉原則: 一個(gè)軟件實(shí)體應(yīng)該通過擴(kuò)展來實(shí)現(xiàn)變化,而不是通過修改已有的代碼來實(shí)現(xiàn)變化
- 依賴倒轉(zhuǎn)原則: 面向接口編程
- 里氏代換原則: 只要父類能出現(xiàn)的地方,子類就可以出現(xiàn),而且替換為子類也不會(huì)產(chǎn)生任何錯(cuò)誤或異常
- 單一職責(zé): 一個(gè)類/方法盡可能只做一件事
- 迪米特法則: 對(duì)象與對(duì)象間因該盡可能獨(dú)立,少調(diào)用其他對(duì)象的方法
- 接口隔離原則: 每個(gè)接口的功能應(yīng)該是獨(dú)立的
11、spring的事務(wù)和分布式事務(wù)
Spring里面的事務(wù)本質(zhì)上是數(shù)據(jù)庫層面的事務(wù),主要是針對(duì)單個(gè)庫中的對(duì)個(gè)表的操作。
分布式事務(wù)主要解決多個(gè)庫直接數(shù)據(jù)一致性問題。
12、分布式事務(wù)的實(shí)現(xiàn)方式
1、使用數(shù)據(jù)庫事務(wù): MySQL 的 XA 事務(wù)、 Oracle 的 RAC 事務(wù)
2、分布式事務(wù)中間件:例如,可以使用 Spring 框架提供的分布式事務(wù)支持,通過配置事務(wù)管理器、事務(wù)傳播行為等來實(shí)現(xiàn)分布式事務(wù)。
3、使用消息隊(duì)列:將事務(wù)操作轉(zhuǎn)化為消息,通過消息隊(duì)列進(jìn)行異步處理,保證事務(wù)的最終一致性。
4、采用分布式鎖:通過對(duì)分布式環(huán)境中的共享資源進(jìn)行加鎖,保證事務(wù)的原子性和一致性??梢允褂萌?Redis、ZooKeeper 等分布式鎖實(shí)現(xiàn)。
5、采用分布式緩存:通過將數(shù)據(jù)緩存在分布式緩存中,減少對(duì)數(shù)據(jù)庫的訪問,提高并發(fā)性能,同時(shí)保證數(shù)據(jù)的一致性。如使用 Redis、Memcached 等分布式緩存技術(shù)。
6、使用 TCC機(jī)制:分為三個(gè)階段,分別在事務(wù)主動(dòng)方、事務(wù)被動(dòng)方和協(xié)調(diào)器之間進(jìn)行。通過 try、commit 和 confirm 操作來保證分布式事務(wù)的一致性。
13、分布式鎖?
1、什么是分布式鎖?
系統(tǒng)內(nèi),有多個(gè)消費(fèi)者,需要對(duì)同一共享數(shù)據(jù)并發(fā)訪問和消費(fèi)時(shí),會(huì)有線程安全問題。例如在秒殺、搶優(yōu)惠券等場(chǎng)景下,商品庫存的數(shù)量是有限的,在高并發(fā)下,會(huì)有"超買"或"超賣"的問題。因此我們需要使用鎖,解決多線程對(duì)共享數(shù)據(jù)并發(fā)訪問的線程安全問題。
2、為什么要用分布式鎖
當(dāng)系統(tǒng)使用分布式架構(gòu)時(shí),服務(wù)會(huì)有多個(gè)實(shí)例存在。需要使用分布式鎖,保證一個(gè)資源在同一時(shí)間內(nèi)只能被一個(gè)服務(wù)的同一個(gè)線程執(zhí)行。
3、redis分布式鎖
通過代碼調(diào)用setnx命令,只在鍵不存在的情況下, 將鍵的值設(shè)置為某個(gè)值。若鍵已經(jīng)存在, 則setnx命令不做任何動(dòng)作。為了能處理"獲取該鎖的請(qǐng)求所在的服務(wù)實(shí)例宕機(jī),會(huì)導(dǎo)致該資源被長(zhǎng)期鎖住,其他請(qǐng)求無法獲取該鎖"這種情況,我們還需要設(shè)置超時(shí)時(shí)間。
4、redis分布式鎖缺陷
1、強(qiáng)依賴redis的可用性,一旦redis宕機(jī),會(huì)導(dǎo)致業(yè)務(wù)系統(tǒng)不可用,因此最好搭建redis集群。
2、因?yàn)閷?duì)鎖設(shè)置了超時(shí)時(shí)間,如果某次請(qǐng)求不能在該次限制時(shí)間內(nèi)完成操作,也會(huì)導(dǎo)致在某些時(shí)刻,多 個(gè)請(qǐng)求獲取到鎖。
解決方案也很簡(jiǎn)單,我們?cè)谡{(diào)用setnx時(shí),將值設(shè)置為該次請(qǐng)求線程的id,并且在服務(wù)實(shí)例內(nèi),設(shè)置一個(gè)守護(hù)線程,當(dāng)鎖快要超時(shí)時(shí),判斷請(qǐng)求是否完成,如果未完成,延長(zhǎng)超時(shí)時(shí)間。
mysql
1、事務(wù)四大特性
原子性、
一致性(事務(wù)執(zhí)行之前數(shù)據(jù)庫是一致的,那么執(zhí)行后也是)、
隔離性(事務(wù)間隔離)、
持久性(數(shù)據(jù)的改變是持久的)
2、事務(wù)的隔離級(jí)別
讀未提交:能讀取到其他事務(wù)沒提交的,臟讀、不可重復(fù)讀、幻讀
讀已提交:讀取到其他事務(wù)提交后的,不可重復(fù)讀、幻讀
可重復(fù)讀:給事務(wù)讀取的數(shù)據(jù)加上版本號(hào),一個(gè)事務(wù)內(nèi)兩次讀取一致,幻讀
串行化:一個(gè)事務(wù)完成才能執(zhí)行下一個(gè)事務(wù)
3、臟讀、重復(fù)讀、幻讀
臟讀:讀到其他事務(wù)還沒有提交的,可能后面又發(fā)生了回滾或修改,就是臟數(shù)據(jù)
不可重復(fù)讀:同一條數(shù)據(jù),同一個(gè)事務(wù)中兩次讀取結(jié)果不一樣
幻讀:同一個(gè)事務(wù)兩次讀取的數(shù)據(jù)條數(shù)不一樣
4、B樹和B+樹的區(qū)別
- B樹特點(diǎn):
1、節(jié)點(diǎn)是排序的
2、一個(gè)節(jié)點(diǎn)可以存多個(gè)元素,這多個(gè)元素也是排序了 - B+樹的特點(diǎn):
1、有B樹的特點(diǎn)
2、葉子節(jié)點(diǎn)之間有指針
3、非葉子節(jié)點(diǎn)的元素,都會(huì)冗余在葉子節(jié)點(diǎn)上(也就是葉子節(jié)點(diǎn)中儲(chǔ)存了所有元素,并排了序的)
5、mysql為什么用B+樹
1、B+樹通過對(duì)數(shù)據(jù)進(jìn)行排序可以提高查詢效率
2、一個(gè)節(jié)點(diǎn)儲(chǔ)存多個(gè)元素,(B樹節(jié)點(diǎn)索引+數(shù)據(jù),B+樹節(jié)點(diǎn)僅索引,葉子節(jié)點(diǎn)索引+數(shù)據(jù))使得B+樹不會(huì)太 高(一個(gè)innodb頁默認(rèn)16k,一般兩層B+樹存2千萬左右數(shù)據(jù))
3、葉子節(jié)點(diǎn)存了所有數(shù)據(jù),可以很好的支持全表掃描、范圍查詢
4、由于B+樹不會(huì)太高,一般三層,B+樹的IO次數(shù)比較穩(wěn)定
6、mysql鎖有哪些
行鎖:鎖住一行數(shù)據(jù),并發(fā)度高
表鎖:鎖住整個(gè)表,并發(fā)讀低(MyISAM 存儲(chǔ)引擎只支持表鎖)
間隙鎖:鎖住某個(gè)區(qū)間
7、mysql的redolog、binlog、undolog
1、binlog用于記錄數(shù)據(jù)庫執(zhí)行的寫入性操作,只有在事務(wù)提交時(shí)才會(huì)記錄biglog,binlog日志有三種格式,分別為STATMENT、ROW和MIXED。(使用場(chǎng)景:主從復(fù)制、數(shù)據(jù)恢復(fù))。
2、Redolog(InnoDB特有的)記錄數(shù)據(jù)頁的變更,而這種變更記錄是沒必要全部保存。mysql每執(zhí)行一條DML語句,先將記錄寫入redo log buffer,后續(xù)再一次性將記錄寫到redo log file。(因?yàn)镮nnodb是以頁為單位進(jìn)行磁盤交互的,1、一個(gè)事務(wù)很可能只修改一個(gè)數(shù)據(jù)頁里面的幾個(gè)字節(jié),這個(gè)時(shí)候?qū)⑼暾臄?shù)據(jù)頁刷到磁盤,太浪費(fèi)資源。2、一個(gè)事務(wù)可能涉及修改多個(gè)數(shù)據(jù)頁,并且這些數(shù)據(jù)頁在物理上并不連續(xù),使用隨機(jī)IO寫入性能太差)
注意:binlog和redo log二者同時(shí)記錄,才能保證當(dāng)數(shù)據(jù)庫發(fā)生宕機(jī)重啟時(shí),數(shù)據(jù)不會(huì)丟失。
redolog 事務(wù)日志、binlog數(shù)據(jù)庫變更的邏輯日志
3、undolog保證事務(wù)原子性,記錄了數(shù)據(jù)的邏輯變化。比如一條INSERT語句,對(duì)應(yīng)一條DELETE的undo log,對(duì)于每個(gè)UPDATE語句,對(duì)應(yīng)一條相反的UPDATE的undo log,這樣在發(fā)生錯(cuò)誤時(shí),就能回滾到事務(wù)之前的數(shù)據(jù)狀態(tài)。
8、mysql二階段提交
Mysql開啟了binlog日志時(shí),那么提交事務(wù)時(shí)就要同時(shí)完成redolog和binlog的事務(wù)寫入。二段提交發(fā)生在redolog和binlog的日志寫入階段,為了滿足數(shù)據(jù)的一致性設(shè)計(jì)。
第一階段:prepare階段,事務(wù)操作記錄到redolog中 ,記錄為prepare狀態(tài)。
第二階段:commit階段,事務(wù)操作記錄到binlog中,把redolog的狀態(tài)改為commit。
如果在寫入redolog之前崩潰,redolog和binlog中為空,滿足一致性
如果在寫入redolog后,寫入binlog前崩潰,redolog中為prepare狀態(tài)狀態(tài),可根據(jù)redolog恢復(fù)。
如果的在binlog寫入后崩潰,那么redolog可以拿著事務(wù)id去執(zhí)行binlog的日志直接提交數(shù)據(jù)。
9、mysql什么時(shí)候會(huì)索引失效
1、沒有使用索引列作為where查詢條件
2、對(duì)索引列進(jìn)行函數(shù)操作(字符串操作、日志操作)
3、對(duì)索引列進(jìn)行類型轉(zhuǎn)換
4、Like查詢時(shí)以“%”開頭
5、查詢條件包括Or,or條件中的每個(gè)條件都不涉及索引列,mysql無法使用索引
6、當(dāng)使用大范圍查詢的時(shí)候
redis
1、緩存雪崩、緩存擊穿、緩存穿透
緩存雪崩:大量key同時(shí)失效
擊穿:多個(gè)請(qǐng)求獲取一個(gè)key,key失效時(shí)發(fā)生擊穿到數(shù)據(jù)庫
穿透:緩存中沒有key,數(shù)據(jù)庫中也沒有,造成資源一直訪問數(shù)據(jù)庫
2、會(huì)員中有大量要過期怎么處理
1、系統(tǒng)不主動(dòng)輪詢,等用戶登陸系統(tǒng)時(shí)觸發(fā)檢查(缺點(diǎn):無法主動(dòng)發(fā)送提醒)
2、用搜索引擎(如es),存儲(chǔ)一份會(huì)員ID和過期時(shí)間到搜索引擎中,搜索引擎能夠?qū)崿F(xiàn)快速檢索
3、使用redis實(shí)現(xiàn),把id和過期時(shí)間存到redis中,使用redis過期提醒功能 ,當(dāng)key過期后觸發(fā)過期事件。
4、使用MQ里面的延遲隊(duì)列,用戶開通會(huì)員后,計(jì)算會(huì)員過期時(shí)間,發(fā)送延遲消息到MQ里面,達(dá)到時(shí)間進(jìn)行消費(fèi)。
多線程
1、線程同步的方法
- Wait(): 讓線程等待,將線程存儲(chǔ)到一個(gè)線程池中。
- Notify(): 喚醒被等待的線程,通常都喚醒線程池中的第一個(gè),讓被喚醒的線程處于臨時(shí)阻塞狀態(tài)。
- NotifyAll(): 喚醒(同一個(gè)鎖的)所有的等待線程。必須在同步代碼塊中調(diào)用此方法,否則拋出異常。wait()和notify()系列方法這樣設(shè)計(jì)的目的是防止死鎖或永久等待發(fā)生。notifyAll()執(zhí)行后,只有一個(gè)線程能得到鎖,其他沒有得到鎖的線程會(huì)繼續(xù)保持在等待狀態(tài)。
注意:
1、調(diào)用完notifyAll()方法后,同步代碼塊中的其他代碼,必須執(zhí)行完后才能將對(duì)象鎖釋放,而不是調(diào)用了notifyAll()方法后立即釋放。
2、在java中,Thread類線程執(zhí)行完run()方法后,一定會(huì)自動(dòng)執(zhí)行notifyAll()方法。
2、什么是ThreadLocal,以及其實(shí)現(xiàn)原理?
ThreadLocal是一種線程隔離機(jī)制,提供了多線程環(huán)境下對(duì)于共享變量訪問的一個(gè)安全性。
在每個(gè)線程里面都有一個(gè)容器,來存儲(chǔ)共享變量的一個(gè)副本,然后每個(gè)線程只對(duì)自己的變量副本進(jìn)行更新操作。
實(shí)現(xiàn)原理:
在Thread類里面有一個(gè)ThreadLocalMap,用來存儲(chǔ)共享變量的副本,線程僅對(duì)這個(gè)副本進(jìn)行操作,不影響全局共享變量的值,實(shí)現(xiàn)數(shù)據(jù)隔離。
3、為什么要使用線程池
1、降低線程開啟關(guān)閉消耗的系統(tǒng)資源
2、提高系統(tǒng)響應(yīng)速度(線程開啟響應(yīng)速度慢)
3、線程管理(線程開啟、關(guān)閉、線程數(shù)量等)
4、線程池執(zhí)行過程
簡(jiǎn)述:任務(wù)進(jìn)線程池,先判斷核心線程是否滿了,滿了就進(jìn)隊(duì)列,隊(duì)列滿了就看最大線程數(shù)是否已達(dá)到,達(dá)到了就按飽和策略處理。未達(dá)到飽和就創(chuàng)建線程執(zhí)行任務(wù)。
核心線程 - 隊(duì)列 - 最大線程數(shù) - 飽和策略
5、線程池的創(chuàng)建方式
1、固定大小線程池
2、緩存線程池
3、單線程線程池
4、延遲任務(wù)線程池
5、單線程延遲任務(wù)線程池
6、搶占式線程池
7、自定義線程池(ThreadPoolExecutor 7個(gè)參數(shù))
6、線程池的7個(gè)參數(shù)
1、核心線程數(shù)
2、最大線程數(shù)
3、線程存活時(shí)間
4、線程存活時(shí)間單位
5、工作隊(duì)列
6、線程工廠
7、拒絕策略
7、線程池隊(duì)列有哪些
1、直接提交隊(duì)列(沒有容量,插入一個(gè)就會(huì)阻塞,執(zhí)行刪除才會(huì)喚醒)
2、有界任務(wù)隊(duì)列(達(dá)到隊(duì)列最大值,開啟新的線程,否則一直是核心線程,該隊(duì)列現(xiàn)進(jìn)先出,有數(shù)組和鏈表兩種實(shí)現(xiàn))
3、無界任務(wù)隊(duì)列(這種隊(duì)列下最大線程數(shù)是無效的,只有核心線程)
4、優(yōu)先任務(wù)隊(duì)列(特殊的無界隊(duì)列,使用平衡二叉樹堆實(shí)現(xiàn),排隊(duì)時(shí)帶有優(yōu)先級(jí))
8、線程池拒絕策略有哪些
1、丟棄任務(wù)拋棄異常
2、直接丟棄任務(wù)
3、丟棄隊(duì)列最前面的任務(wù)
4、調(diào)用線程(提交任務(wù)的線程)直接執(zhí)行此任務(wù)
5、new RejectedExecutionHandler() 自定義拒絕策略
9、線程池的關(guān)閉
shutdown 當(dāng)任務(wù)隊(duì)列為空的時(shí)候,才關(guān)閉線程池
shutdownnow 直接停止
10、使用無界隊(duì)列的線程池會(huì)導(dǎo)致內(nèi)存飆升嗎?
會(huì)的,newFixedThreadPool使用了無界的阻塞隊(duì)列LinkedBlockingQueue,如果線程獲取一個(gè)任務(wù)后,任務(wù)的執(zhí)行時(shí)間比較長(zhǎng),會(huì)導(dǎo)致隊(duì)列的任務(wù)越積越多,導(dǎo)致機(jī)器內(nèi)存使用不停飆升, 最終導(dǎo)致OOM。
11、線程創(chuàng)建的幾種方式
1、繼承Thread,重寫run方法
2、實(shí)現(xiàn)Runnable接口創(chuàng)建線程(無返回值)
3、實(shí)現(xiàn)Callable接口+Future創(chuàng)建線程(有返回值,可拋出經(jīng)過檢查的異常)
12、Future有什么用
可以對(duì)正在執(zhí)行的任務(wù)進(jìn)行維護(hù)操作(取消任務(wù)、獲取任務(wù)執(zhí)行結(jié)果、判斷任務(wù)是否已完成等)。
13、FutureTask有什么用
1、可取消的異步計(jì)算;
2、利用開始和取消計(jì)算的方法、查詢計(jì)算是否完成的方法和獲取計(jì)算結(jié)果的方法,此類提供了對(duì)Future的基本實(shí)現(xiàn);
3、可使用FutureTask包裝Callable或Runnable對(duì)象因?yàn)镕utureTask實(shí)現(xiàn)了Runnable,所以可將FutureTask提交給Executor執(zhí)行;
4、僅在計(jì)算完成時(shí)才能獲取結(jié)果;如果計(jì)算尚未完成,則阻塞get方法一旦計(jì)算完成,就不能再重新開始或取消計(jì)算;
14、線程的生命周期(狀態(tài))
- 新建
- 可運(yùn)行
- 阻塞(處于阻塞狀態(tài)的線程不會(huì)占用CPU資源,阻塞IO操作執(zhí)行完,線程可轉(zhuǎn)換為可運(yùn)行狀態(tài))
- 等待(執(zhí)行object.wait()或thread.join()變成等待,notify()或加入的線程執(zhí)行完畢會(huì)轉(zhuǎn)為可運(yùn)行)
- 固定時(shí)間等待(不會(huì)無限期地等待,如果線程沒有在指定時(shí)間內(nèi)完成操作,自動(dòng)轉(zhuǎn)換為可運(yùn)行)
- 終止?fàn)顟B(tài)
15、 i++是線程安全的嗎
i++不是原子性操作,執(zhí)行它包括三個(gè)操作:讀i的值、i+1、將新值保存到內(nèi)存。
所以它不是線程安全的。
16、可重入鎖ReentrantLock
可重入:當(dāng)一個(gè)線程獲得一個(gè)對(duì)象鎖后,再次請(qǐng)求該對(duì)象鎖時(shí),可以再次獲得該對(duì)象的鎖。
16.1、Synchronized和ReentrantLock的相同
1、都是獨(dú)占鎖
2、都是可重入的
16.2、Synchronized和ReentrantLock的不同
1、ReentrantLock是Java層面的實(shí)現(xiàn),手動(dòng)加鎖手動(dòng)解鎖,synchronized是JVM層面的實(shí)現(xiàn)。
2、ReentrantLock可以實(shí)現(xiàn)公平和非公平鎖。
3、ReentantLock獲取鎖時(shí),限時(shí)等待,配合重試機(jī)制更好的解決死鎖
4、ReentrantLock可響應(yīng)中斷
5.使用synchronized結(jié)合Object上的wait和notify方法可以實(shí)現(xiàn)線程間的等待通知機(jī)制。ReentrantLock結(jié)合Condition接口同樣可以實(shí)現(xiàn)這個(gè)功能。
17、synchronized可重入鎖的實(shí)現(xiàn)原理
1、每一個(gè)可重入鎖都會(huì)關(guān)聯(lián)一個(gè)線程ID和一個(gè)鎖狀態(tài)status。
2、當(dāng)一個(gè)線程請(qǐng)求方法時(shí),會(huì)去檢查鎖狀態(tài),
- 如果鎖狀態(tài)是0,代表該鎖沒有被占用,直接進(jìn)行CAS操作獲取鎖,將線程ID替換成自己的線程ID。
- 如果鎖狀態(tài)不是0,代表有線程在訪問該方法。此時(shí),如果線程ID是自己的線程ID,
– 可重入鎖,將status自增1,然后獲取到該鎖,進(jìn)而執(zhí)行相應(yīng)的方法。
– 非重入鎖,進(jìn)入阻塞隊(duì)列等待。
3、釋放鎖時(shí),
- 可重入鎖,每一次退出方法,就會(huì)將status減1,直至status的值為0,最后釋放該鎖。
- 非可重入鎖,直接就會(huì)釋放該鎖。
Activiti流程引擎
1、Activiti工作流的主要組件
Activity(活動(dòng))、workflow(流程)、workItem(工作項(xiàng))、rule(規(guī)則)、狀態(tài)(state)
2、Activiti工作流有什么優(yōu)勢(shì)
1、提供了可視化的方式進(jìn)行描述和執(zhí)行業(yè)務(wù)流程
2、支持業(yè)務(wù)邏輯的可重用性和模塊化開發(fā)
3、支持監(jiān)控和追蹤業(yè)務(wù)流程
4、擴(kuò)展性比較好
3、Activiti工作流service有哪些
1、RepositoryService 流程定義和部署對(duì)象
2、RuntimeService 執(zhí)行管理,包括流程實(shí)例和執(zhí)行對(duì)象
3、TaskService 執(zhí)行任務(wù)(正在流程中的)
4、HistoryService 歷史管理
5、IdentityService 用戶角色
4、流程實(shí)例和執(zhí)行對(duì)象的區(qū)別
流程實(shí)例:一個(gè)流程中,流程實(shí)例只有一個(gè)
流程對(duì)象:按照流程定義的規(guī)則執(zhí)行一次操作,一個(gè)流程中執(zhí)行對(duì)象可以多個(gè)
5、工作流中一個(gè)任務(wù)完成后,存在多條連線,如何處理
1、使用流程變量
2、當(dāng)一個(gè)任務(wù)完成之后,根據(jù)這幾條連線的條件和設(shè)置流程變量,例如${流程變量名==’值’},{}符號(hào)是布爾類型,判斷走哪條線。
6、Activiti工作流中排他網(wǎng)關(guān)和并行網(wǎng)關(guān)都能執(zhí)行什么功能
排他網(wǎng)關(guān):分支,通過連線的流程變量,判斷執(zhí)行哪條連線,如果條件不符合,默認(rèn)離開連線。只執(zhí)行其中一個(gè)流程
并行網(wǎng)關(guān):可以同時(shí)執(zhí)行多個(gè)流程,直到總流程結(jié)束。可以對(duì)流程進(jìn)行分支和聚合。
7、分配個(gè)人任務(wù)的三種方式
1、直接給值,在Xxxx.bpmn中指定
2、流程變量${流程變量名}或#{}
3、用監(jiān)聽類指定任務(wù)辦理人(setAssgnee)
8、個(gè)人任務(wù)和組任務(wù)的查詢一樣嗎?
1、不一樣
2、都是用TaskService完成
3、個(gè)人任務(wù)(taskAssgnee),組任務(wù)(taskCandidateUser)
4、數(shù)據(jù)庫存放,個(gè)人任務(wù):參與,組任務(wù):類型、參與、候選
綜合性問題
1、生產(chǎn)環(huán)境發(fā)生內(nèi)存泄露怎么排查問題?
- 1、什么是內(nèi)存泄露
程序在運(yùn)行過程中,因?yàn)槟承┰驅(qū)е虏恍枰膶?duì)象,仍然占用jvm內(nèi)存空間并且無法回收。導(dǎo)致占用內(nèi) 存越來越大出現(xiàn)OOM。 - 2、內(nèi)存泄露出現(xiàn)的現(xiàn)象
頻繁FULL GC、內(nèi)存暫用量過大無法釋放 - 3、怎么定位問題?
是否是內(nèi)存泄露?老年代逐步增長(zhǎng)?Full gc卡頓?年輕代內(nèi)存一直在高位無法釋放?頻繁full GC?
使用jstat命令查看虛擬機(jī)中各個(gè)內(nèi)存的使用情況、GC情況
使用dump工具把內(nèi)存dump下來,使用MAT工具進(jìn)行分析。Mat會(huì)分析dump文件的內(nèi)容,給出分析結(jié)果,定位到有問題的類,然后找到有問題代碼進(jìn)行優(yōu)化。
一般情況可是循環(huán)引用、內(nèi)存對(duì)象泄露沒有銷毀、動(dòng)態(tài)分配內(nèi)存后沒有釋放、長(zhǎng)期持有對(duì)象引用、資源未關(guān)閉等情況造成的內(nèi)存泄露