和信貸面試
HashMap的hash是如何計算的? 負載因子是什么?什么時候rehash的?
- hash的代碼如下。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Java 左移運算 << ,丟棄最高位,0補最低位;帶符號右移運算 >> 符號位不變,左邊補上符號位;無符號右移運算 >>> 忽略了符號位擴展,0補最高位
^是異或運算符。如果a、b兩個值不相同,則異或結果為1。如果a、b兩個值相同,異或結果為0
負載因子 loadFactor,默認值是0.75。 threshold = loadFactor * capacity。
-
什么時候rehash呢?
插入數(shù)據(jù)時,如果
transient Node<K,V>[] table變量為null,則進行初始化。-
putVal成功之后,size代表當前HashMap中的元素個數(shù)。
if (++size > threshold) resize();
ConcurrentHashMap是如何實現(xiàn)多線程安全的呢?
- jdk1.8中,使用cas + sychornized 來實現(xiàn)線程安全。
ReentrantLock 的實現(xiàn)原理
- ReentrantLock 實現(xiàn)鎖的底層原語是LockSupport.park()?unpark()?
- 在調用lock()方法是,會首先用cas樂觀鎖嘗試獲取鎖,在獲取鎖失敗的情況下會將當前線程封裝成一個node存入一個雙端隊列。
- 在調用unlock()方法時,如果隊列不為空,則會將隊列中的下一個線程喚醒。
- 如果不使用雙端隊列,還有別的實現(xiàn)方式嗎?這里回答的不太好,說官方的實現(xiàn)方式即是最優(yōu)的實現(xiàn)方式,暫時想不到最優(yōu)的實現(xiàn)方式。
分布式鎖的實現(xiàn)方式
- redis setnx(key,value,expiretime)
- 實現(xiàn)原理
- zookeeper
- zookeeper在創(chuàng)建分布式鎖時會在leader節(jié)點創(chuàng)建一個目錄,當有 (n / 2) + 1 個節(jié)點返回ack時,鎖即獲取成功。
redis 實現(xiàn)原理 (技術總監(jiān)面)
- redis 網(wǎng)絡模型, 純內存操作,高效的數(shù)據(jù)結構,數(shù)據(jù)備份方式四個主題一一詳細的詢問。
Mysql (技術總監(jiān)面)
- MySQL 索引類型(B+Tree, Hash), B+tree是一個什么樣的數(shù)據(jù)結構。
- 分布分表
- 分庫分表策略
- 當分庫分表達到數(shù)千個數(shù)據(jù)庫時,如何進行匯總查詢(要求在一個http request response timeout 內返回)。
- 我回答將查詢同時發(fā)送到數(shù)千個實例,取到結果后本地內存merge , sort 。但是對此回答不滿意,后來沒有思路了,只能說在MySQL技術范疇之內我的技術儲備能夠解決的方法僅此一個了。
火花思維面試
手寫代理模式(技術總監(jiān)面)
dubbo 一次request發(fā)送完畢之后,如何獲取相應結果的 (技術總監(jiān)面,他說dubbo請求一個請求拿到結果之后下一個才能發(fā)送請求)
-
在 dubbo org.apache.dubbo.rpc.protocol.dubbo.ChannelWrappedInvoker#doInvoke 中可以看到
currentClient.request(inv).get()這行請求的關鍵代碼if (closed) { throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!"); } // create request. Request req = new Request(); req.setVersion(Version.getProtocolVersion()); req.setTwoWay(true); req.setData(request); DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout); try { channel.send(req); } catch (RemotingException e) { future.cancel(); throw e; } return future;
這行代碼的調用如上,可以看到dubbo client 組裝了請求參數(shù)之后,就通過 `
if (closed) { throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!"); } // create request. Request req = new Request(); req.setVersion(Version.getProtocolVersion()); req.setTwoWay(true); req.setData(request); DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout); try { channel.send(req); } catch (RemotingException e) { future.cancel(); throw e; } return future;
這行代碼的調用如上,可以看到dubbo client 組裝了請求參數(shù)之后,就通過`DefaultFuture.newFuture(channel, req, timeout)` 構造了一個DefaultFuture 。通過 channel將請求`send`即返回。這里并沒有拿到response 。但是在返回`DefaultFuture`之后,在`dubbo org.apache.dubbo.rpc.protocol.dubbo.ChannelWrappedInvoker#doInvoke `中的 `currentClient.request(inv)`拿到`DefaultFuture`之后即調用`get`方法返回了RPC請求的結果。
```java
if (timeout <= 0) {
timeout = Constants.DEFAULT_TIMEOUT;
}
if (!isDone()) {
long start = System.currentTimeMillis();
lock.lock();
try {
while (!isDone()) {
done.await(timeout, TimeUnit.MILLISECONDS);
if (isDone() || System.currentTimeMillis() - start > timeout) {
break;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
if (!isDone()) {
throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));
}
}
return returnFromResponse();
```
get的實際邏輯如上,線程在請求參數(shù)發(fā)送出去之后即進入while循環(huán)中進行阻塞等待,通過設置阻塞等待的時間,如果超過指定時間服務端還沒有相應結果則會跳出循環(huán),拋出超時異常。如果在timeout時間范圍內RPC響應結果返回,則 有如下代碼
```java
private void doReceived(Response res) {
lock.lock();
try {
response = res;
done.signalAll();
} finally {
lock.unlock();
}
if (callback != null) {
invokeCallback(callback);
}
}
```
此時將會喚醒前面`get` 方法 while中的線程阻塞, 將結果返回。這就是一個請求響應的過程。
## redis 集群的幾種實現(xiàn)方式(技術總監(jiān)面)
> 這個問題回答的不是很好,只是簡單的說是通過 redisClient 來實現(xiàn)的客戶端分片,redis集群互相不感知。然后被問到當集群中有一臺掛了會有什么樣的結果時,就說到了一致性hash。當問掛了的數(shù)據(jù)對線上的操作造成影響時怎么辦,然后回答說通過redis一主一叢。但是這個問題大體上來回回答的不是特別好。應當明確redis實現(xiàn)集群的幾種方式(客戶端分片,redis 原生cluster等),實現(xiàn)原理,`故障應對策略`等。
##