2019年_BATJ大廠面試題總結-美團篇

1.mybatis怎麼實現orm 說說自己理解 讓你落地怎麼去做

詳解答案:https://blog.csdn.net/u010633266/article/details/92851528

2.PU飆升,只有JAVA進程,如何解決?

有圖答案:https://cloud.tencent.com/developer/ask/55198
代碼答案:https://blog.csdn.net/weixin_30323961/article/details/95639909

3.Redis和ZooKeeper如何實現分佈式鎖以及區別?

Redis實現分佈式鎖思路
基於Redis實現分佈式鎖(setnx)setnx也可以存入key,如果存入key成功返回1,如果存入的key已經存在了,返回0.

Zookeeper實現分佈式鎖思路
基於Zookeeper實現分佈式鎖 Zookeeper是一個分佈式協調工具,在分佈式解決方案中。
多個客戶端(jvm),同時在zookeeper上創建相同的一個臨時節點,因爲臨時節點路徑是保證唯一,只要誰能夠創建節點成功,誰就能夠獲取到鎖,沒有創建成功節點,就會進行等待,當釋放鎖的時候,採用事件通知給客戶端重新獲取鎖的資源。

Redis實現分佈式鎖與Zookeeper實現分佈式鎖區別
相同點
實現分佈式鎖最終是通過什麼方式?
在集羣環境下,保證只允許有一個jvm進行執行。

不同點
從技術上分析

Redis 是nosql數據,主要特點緩存;

Zookeeper是分佈式協調工具,主要用於分佈式解決方案。

實現思路
核心通過獲取鎖、釋放鎖、死鎖問題

獲取鎖

Zookeeper
多個客戶端(jvm),會在Zookeeper上創建同一個臨時節點,因爲Zookeeper節點命名路徑保證唯一,不允許出現重複,只要誰能夠先創建成功,誰能夠獲取到鎖。
Redis
多個客戶端(jvm),會在Redis使用setnx命令創建相同的一個key,因爲Redis的key保證唯一,不允許出現重複,只要誰能夠先創建成功,誰能夠獲取到鎖。

釋放鎖

Zookeeper使用直接關閉臨時節點session會話連接,因爲臨時節點生命週期與session會話綁定在一塊,如果session會話連接關閉的話,該臨時節點也會被刪除。
這時候客戶端使用事件監聽,如果該臨時節點被刪除的話,重新進入盜獲取鎖的步驟。

Redis在釋放鎖的時候,爲了確保是鎖的一致性問題,在刪除的redis 的key時候,需要判斷同一個鎖的id,纔可以刪除。

共同特徵:如何解決死鎖現象問題

Zookeeper使用會話有效期方式解決死鎖現象。

Redis 是對key設置有效期解決死鎖現象

性能角度考慮

因爲Redis是NoSQL數據庫,相對比來說Redis比Zookeeper性能要好。

可靠性
從可靠性角度分析,Zookeeper可靠性比Redis更好。

因爲Redis有效期不是很好控制,可能會產生有效期延遲;

Zookeeper就不一樣,因爲Zookeeper臨時節點先天性可控的有效期,所以相對來說Zookeeper比Redis更好

4.String 和 Hash的使用場景

答案:Redis 數據類型String Hash list set使用場景

5.StringBuilder和StringBuffer的區別?

答案:圖析:String,StringBuffer與StringBuilder的區別
在這裏插入圖片描述

6.ZooKeeper如何實現數據一致性?

答案:https://blog.csdn.net/weixin_44240370/article/details/98479283

7.分佈式鎖的實現原理

最詳細答案:https://www.cnblogs.com/lalalagq/p/9971458.html

8.簡單講一下你使用過的設計模式,然後讓我寫了一個線程安全的單例

我這裏只提供最優的一種寫法(多線程環境下懶漢式單例模式實現),需要詳細看的請到我推薦的博客中學習。
https://www.cnblogs.com/jiuyi/p/6105037.html

package test;
 
/**
 * @time 2019/7/19
 * @author ZF
 * 功能:實現多線程環境下懶漢式單例模式。
 */
 
public class SingletonDemo {
	private static SingletonDemo instance = null;
	private SingletonDemo(){}
	public SingletonDemo getInstance(){
		if(instance == null){
			synchronized (this) {
				if(instance == null){
					instance = new SingletonDemo();
				}
			}
		}
	return instance;
	}
}

9.線程有幾個狀態,就緒和阻塞有什麼不同,知道線程池的實現原理不,核心參數講一下,講一下線程池分配線程的方法,項目中用過幾種加鎖的方法,threadlocal的實現原理?

1.線程五種狀態(新建、就緒、運行、阻塞、死亡)
2.阻塞狀態的進程還不具務執行的條件,即使放到處理機上能執行;就緒狀態的進程具備了執行的所有條件,放在處理機上就能執行。
就緒態:
進程所有的執行條件都滿足,只等着cpu來調度;
當前是就緒態的話,要麼是要等待運行,要麼是運行時間片用完又回到了就緒態。

阻塞態:
進程不具備執行條件,比如需等待I/O;
阻塞態是運行過程中,條件不滿足了被阻塞,等到條件滿足了,回到就緒態。
3.ThreadLocal的應用與實現原理

10.一個算法題假設有N級臺階每次可以上1或者2 階,有幾種方法上N級臺階?

一、 題目分析

這個問題本質上是斐波那契數列,假設只有一個臺階,那麼只有一種跳法,那就是一次跳一級,f(1)=1;如果有兩個臺階,那麼有兩種跳法,第一種跳法是一次跳一級,第二種跳法是一次跳兩級,f(2)=2。如果有大於2級的n級臺階,那麼假如第一次跳一級臺階,剩下還有n-1級臺階,有f(n-1)種跳法,假如第一次條2級臺階,剩下n-2級臺階,有f(n-2)種跳法。這就表示f(n)=f(n-1)+f(n-2)。將上面的斐波那契數列代碼稍微改一下就是本題的答案。我們來看一下代碼的實現。

二、斐波那契數列法

public class Test {
    static final int s = 100; //自定義的臺階數

    static int compute(int stair){
        if ( stair <= 0){
            return 0;
        }
        if (stair == 1){
            return 1;
        }
        if (stair == 2){
            return 2;
        }
        return compute(stair-1) + compute(stair-2);
    }

    public static void main(String args[]) {
        System.out.println("共有" + compute(s) + "種走法");
    }
}

三、 走臺階問題的簡單解決算法

但我自己對於這個題目最早的想法是使用樹(多叉樹)的方式,100爲根節點,每次選擇的分支有兩種(1、2),然後生成深度爲1的樹,再從每個2級節點延伸出1、2兩個分支,直到所有節點的值<=0,最後統計出所有值爲0的葉子節點的數目,就是結果。

不過自己想法實際上把問題複雜化了,下面這種使用遞歸方式實現的算法本質上和我的思想差不多,但是很明顯下面這個算法會簡單很多。接下來我們來看看這個算法的實現方式。

public class Test {
    static final int s = 100;  //自定義的臺階數
    static int len = 0, sum = 0;

    //最多也只有走100步就到了
    static int step[] = new int[s];

    static void compute(final int stair) {
        if (stair < 0)
            return;

        //表示已經走完了
        if (stair == 0) {
            printSum();
            sum++;
            return;
        }

        //每次到下一步選擇時都可以走1-2步
        for (int i = 1; i <= 2; i++) {
            step[len] = i;
            len++;

            //進行下一步的迭代,迭代完之後將每後加上的一步去掉,換成其它的步數(如從1換成2)
            compute(stair - i);
            len--;
        }
    }

    static void printSum() {
        System.out.print("走法:");
        for (int i = 0; i < len; i++)
            System.out.print(step[i] + " ");
        System.out.println();
    }

    public static void main(String args[]) {
        compute(s);
        System.out.println("共有" + sum + "種走法");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章