- 容器基本內(nèi)容
- HashMap的底層
- 多線程同步方法
- 消息隊(duì)列問(wèn)題
- 設(shè)計(jì)模式中的生產(chǎn)者消費(fèi)者模型
- 同步異步接口
- Mysql兩種引擎的區(qū)別
- mybatis與hibernate的區(qū)別
- Struts2 攔截器與Spring AOP的區(qū)別
- HashMap容量為什么是2^n
- HashMap的負(fù)載因子
1. 容器基本內(nèi)容
Java集合類里面最基本的接口如下:


Collection:一個(gè)獨(dú)立元素的序列,這些元素都服從一條或者多條規(guī)則。 List必須按照插入的順序保存元素,而set不能有重復(fù)的元素。Queue按照排隊(duì)規(guī)則來(lái)確定對(duì)象產(chǎn)生的順序(通常與它們被插入的順序相同)。
Map:一組成對(duì)的“鍵值對(duì)”對(duì)象,允許你使用鍵來(lái)查找值。
2. HashMap的底層
HashMap是基于哈希表的Map接口的非同步實(shí)現(xiàn),Java最基本數(shù)據(jù)結(jié)構(gòu)就是兩種,一種是數(shù)組,一種是引用。所有的數(shù)據(jù)結(jié)構(gòu)都可以用這兩個(gè)基本結(jié)構(gòu)來(lái)構(gòu)造的,HashMap也不例外。
HashMap實(shí)際上是一個(gè)“鏈表散列”的數(shù)據(jù)結(jié)構(gòu),即數(shù)組和鏈表的結(jié)合體。HashMap底層就是一個(gè)數(shù)組結(jié)構(gòu),數(shù)組中的每一項(xiàng)又是一個(gè)鏈表。當(dāng)新建一個(gè)HashMap的時(shí)候,就會(huì)初始化一個(gè)數(shù)組。Entry就是數(shù)組中的元素,每個(gè) Map.Entry 其實(shí)就是一個(gè)key-value對(duì),它持有一個(gè)指向下一個(gè)元素的引用,這就構(gòu)成了鏈表。
3. 多線程同步方法
為何要使用同步?
java允許多線程并發(fā)控制,當(dāng)多個(gè)線程同時(shí)操作一個(gè)可共享的資源變量時(shí)(如數(shù)據(jù)的增刪改查), 將會(huì)導(dǎo)致數(shù)據(jù)不準(zhǔn)確,相互之間產(chǎn)生沖突,因此加入同步鎖以避免在該線程沒有完成操作之前,被其他線程的調(diào)用, 從而保證了該變量的唯一性和準(zhǔn)確性。1.同步方法
即有synchronized關(guān)鍵字修飾的方法。
由于java的每個(gè)對(duì)象都有一個(gè)內(nèi)置鎖,當(dāng)用此關(guān)鍵字修飾方法時(shí), 內(nèi)置鎖會(huì)保護(hù)整個(gè)方法。在調(diào)用該方法前,需要獲得內(nèi)置鎖,否則就處于阻塞狀態(tài)。
public synchronized void save(){
}
注: synchronized關(guān)鍵字也可以修飾靜態(tài)方法,此時(shí)如果調(diào)用該靜態(tài)方法,將會(huì)鎖住整個(gè)類
- 同步代碼塊
即有synchronized關(guān)鍵字修飾的語(yǔ)句塊。 被該關(guān)鍵字修飾的語(yǔ)句塊會(huì)自動(dòng)被加上內(nèi)置鎖,從而實(shí)現(xiàn)同步。
- 同步代碼塊
synchronized(object){
}
- 3.使用特殊域變量(volatile)實(shí)現(xiàn)線程同步
volatile關(guān)鍵字為域變量的訪問(wèn)提供了一種免鎖機(jī)制, 使用volatile修飾域相當(dāng)于告訴虛擬機(jī)該域可能會(huì)被其他線程更新, 因此每次使用該域就要重新計(jì)算,而不是使用寄存器中的值 volatile不會(huì)提供任何原子操作,它也不能用來(lái)修飾final類型的變量。
//需要同步的變量加上volatile
private volatile int account = 100;
- 使用重入鎖
ReenreantLock類的常用方法有:
ReentrantLock() : 創(chuàng)建一個(gè)ReentrantLock實(shí)例
lock() : 獲得鎖
unlock() : 釋放鎖
- 使用重入鎖
//需要聲明這個(gè)鎖
private Lock lock = new ReentrantLock();
lock.lock();
try{
account += money;
}finally{
lock.unlock();
}
- 5.使用局部變量實(shí)現(xiàn)線程同步
如果使用ThreadLocal管理變量,則每一個(gè)使用該變量的線程都獲得該變量的副本,
副本之間相互獨(dú)立,這樣每一個(gè)線程都可以隨意修改自己的變量副本,而不會(huì)對(duì)其他線程產(chǎn)生影響。
ThreadLocal 類的常用方法
ThreadLocal() : 創(chuàng)建一個(gè)線程本地變量
get() : 返回此線程局部變量的當(dāng)前線程副本中的值
initialValue() : 返回此線程局部變量的當(dāng)前線程的"初始值"
set(T value) : 將此線程局部變量的當(dāng)前線程副本中的值設(shè)置為value
public class Bank{
//使用ThreadLocal類管理共享變量account
private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue(){
return 100;
}
};
public void save(int money){
account.set(account.get()+money);
}
public int getAccount(){
return account.get();
}
}
上面的五種偏底層
- 6.使用原子變量實(shí)現(xiàn)線程同步
原子操作就是指將讀取變量值、修改變量值、保存變量值看成一個(gè)整體來(lái)操作即-這幾種行為要么同時(shí)完成,要么都不完成。
在java的util.concurrent.atomic包中提供了創(chuàng)建了原子類型變量的工具類
class Bank {
private AtomicInteger account = new AtomicInteger(100);
public AtomicInteger getAccount() {
return account;
}
public void save(int money) {
account.addAndGet(money);
}
}
- 7.使用阻塞隊(duì)列實(shí)現(xiàn)線程同步
阻塞隊(duì)列與普通隊(duì)列的區(qū)別在于,當(dāng)隊(duì)列是空的時(shí),從隊(duì)列中獲取元素的操作將會(huì)被阻塞,或者當(dāng)隊(duì)列是滿時(shí),往隊(duì)列里添加元素的操作會(huì)被阻塞。
同時(shí),阻塞隊(duì)列里面的put、take方法是被加:synchronized 同步限制。

4. 消息隊(duì)列問(wèn)題
消息隊(duì)列在實(shí)際應(yīng)用中常用的使用場(chǎng)景。異步處理,應(yīng)用解耦,流量削鋒和消息通訊四個(gè)場(chǎng)景。
-
- 異步處理
引入消息隊(duì)列,將不是必須的業(yè)務(wù)邏輯,異步處理。
- 異步處理

- 應(yīng)用解耦
場(chǎng)景說(shuō)明:用戶下單后,訂單系統(tǒng)需要通知庫(kù)存系統(tǒng)。傳統(tǒng)的做法是,訂單系統(tǒng)調(diào)用庫(kù)存系統(tǒng)的接口。假如庫(kù)存系統(tǒng)無(wú)法訪問(wèn),則訂單減庫(kù)存將失敗,從而導(dǎo)致訂單失敗??梢酝ㄟ^(guò)消息隊(duì)列將兩者解耦和。
- 應(yīng)用解耦


- 流量削鋒
流量削鋒也是消息隊(duì)列中的常用場(chǎng)景,一般在秒殺或團(tuán)搶活動(dòng)中使用廣泛。
場(chǎng)景說(shuō)明:秒殺活動(dòng),一般會(huì)因?yàn)榱髁窟^(guò)大,導(dǎo)致流量暴增,應(yīng)用掛掉。為解決這個(gè)問(wèn)題,一般需要在應(yīng)用前端加入消息隊(duì)列。
- 流量削鋒

- 日志處理
日志處理是指將消息隊(duì)列用在日志處理中,比如Kafka的應(yīng)用,解決大量日志傳輸?shù)膯?wèn)題。
- 日志處理

5. 設(shè)計(jì)模式中的生產(chǎn)者消費(fèi)者模型:
生產(chǎn)者消費(fèi)者問(wèn)題是線程模型中的經(jīng)典問(wèn)題:生產(chǎn)者和消費(fèi)者在同一時(shí)間段內(nèi)共用同一存儲(chǔ)空間,生產(chǎn)者向空間里生產(chǎn)數(shù)據(jù),而消費(fèi)者取走數(shù)據(jù)。
生產(chǎn)者消費(fèi)者模式是通過(guò)一個(gè)容器來(lái)解決生產(chǎn)者和消費(fèi)者的強(qiáng)耦合問(wèn)題。生產(chǎn)者和消費(fèi)者彼此之間不直接通訊,而通過(guò)阻塞隊(duì)列來(lái)進(jìn)行通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)之后不用等待消費(fèi)者處理,直接扔給阻塞隊(duì)列,消費(fèi)者不找生產(chǎn)者要數(shù)據(jù),而是直接從阻塞隊(duì)列里取,阻塞隊(duì)列就相當(dāng)于一個(gè)緩沖區(qū),平衡了生產(chǎn)者和消費(fèi)者的處理能力。
這個(gè)阻塞隊(duì)列就是用來(lái)給生產(chǎn)者和消費(fèi)者解耦的。
6. 同步異步接口:
同步交互:指發(fā)送一個(gè)請(qǐng)求,需要等待返回,然后才能夠發(fā)送下一個(gè)請(qǐng)求,有個(gè)等待過(guò)程;
異步交互:指發(fā)送一個(gè)請(qǐng)求,不需要等待返回,隨時(shí)可以再發(fā)送下一個(gè)請(qǐng)求,即不需要等待。
7. Mysql兩種引擎的區(qū)別:

主要區(qū)別:
MYIASM為默認(rèn)引擎。
1、MyIASM是非事務(wù)安全的,而InnoDB是事務(wù)安全的
2、MyIASM鎖的粒度是表級(jí)的,而InnoDB支持行級(jí)鎖
3、MyIASM支持全文類型索引,而InnoDB不支持全文索引
4、MyIASM相對(duì)簡(jiǎn)單,效率上要優(yōu)于InnoDB,小型應(yīng)用可以考慮使用MyIASM
5、MyIASM表保存成文件形式,跨平臺(tái)使用更加方便
8. mybatis與hibernate的區(qū)別
Mybatis學(xué)習(xí)門檻低,簡(jiǎn)單易學(xué),程序員直接編寫原生態(tài)sql,可嚴(yán)格控制sql執(zhí)行性能,靈活度高,非常適合對(duì)關(guān)系數(shù)據(jù)模型要求不高的軟件開發(fā)
Hibernate對(duì)象/關(guān)系映射能力強(qiáng),數(shù)據(jù)庫(kù)無(wú)關(guān)性好,對(duì)于關(guān)系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開發(fā)可以節(jié)省很多代碼,提高效率。但是Hibernate的學(xué)習(xí)門檻高。

9. Struts2 攔截器與Spring AOP的區(qū)別
Struts2 簡(jiǎn)單來(lái)說(shuō),就是一個(gè)攔截器棧也就是一系列的攔截器。處理用戶的請(qǐng)求,OGNL的使用,表單驗(yàn)證等都是默認(rèn)的攔截器在起作用。
AOP,面向切面編程,考慮對(duì)哪些方法進(jìn)行攔截,攔截后怎么處理,這些關(guān)注點(diǎn)稱之為橫切關(guān)注點(diǎn)。所以spring的攔截器,主要體現(xiàn)在AOP的事務(wù)管理方面,還有比如一些錯(cuò)誤或者異常的日志的顯示也是通過(guò)配置spring的log攔截器來(lái)實(shí)現(xiàn)的。
廣義來(lái)說(shuō)spring和struts2的攔截器的工作原理都一樣。
10. HashMap的容量為什么是2^n?
static int indexFor(int h,int length) {
return h & (length-1);
}
key的hashCode經(jīng)過(guò)hash后,為了讓其在table(table為hashMap的entry[])的范圍內(nèi),需要再hash一次。這里實(shí)際上是采用的“除余法”。
如果length是2的N次方,那么數(shù)h對(duì)length的模運(yùn)算結(jié)果等價(jià)于a和(length-1)的按位與運(yùn)算,也就是 h%length <=> h&(length-1)。
位運(yùn)算當(dāng)然比取余效率高,所以HashMap容量要求為2^n。
11. HashMap的負(fù)載因子
負(fù)載因子默認(rèn)是0.75,會(huì)影響HashMap的性能。
threshold = (int)(capacity * loadFactor);
threshold為HashMap的size最大值
所以負(fù)載因子越大則散列表的裝填程度越高,也就是能容納更多的元素,元素多了,鏈表就長(zhǎng)了,所以此時(shí)索引效率就會(huì)降低。
