面試基本概念原理最佳實踐

1) Java中什麼是競態條件? 舉個例子說明。

競態條件會致使程序在併發狀況下出現一些bugs。多線程對一些資源的競爭的時候就會產生競態條件,若是首先要執行的程序競爭失敗排到後面執行了, 那麼整個程序就會出現一些不肯定的bugs。這種bugs很難發現並且會重複出現,由於線程間的隨機競爭。一個例子就是無序處理html

競態條件(Race Condition):計算的正確性取決於多個線程的交替執行時序時,就會發生競態條件。java

最多見的競態條件爲:mysql

一,先檢測後執行。執行依賴於檢測的結果,而檢測結果依賴於多個線程的執行時序,而多個線程的執行時序一般狀況下是不固定不可判斷的,從而致使執行結果出現各類問題。linux

對於main線程,若是文件a不存在,則建立文件a,可是在判斷文件a不存在以後,Task線程建立了文件a,這時候先前的判斷結果已經失效,(main線程的執行依賴了一個錯誤的判斷結果)此時文件a已經存在了,可是main線程仍是會繼續建立文件a,致使Task線程建立的文件a被覆蓋、文件中的內容丟失等等問題。c++

 

多線程環境中對同一個文件的操做要加鎖。面試

和大多數併發錯誤同樣,競態條件不老是會產生問題,還須要不恰當的執行時序 算法

 

2)Java中有哪些實現併發編程的方法

1. synchronized關鍵字spring

2. 使用繼承自Object類的wait、notify、notifyAll方法
3. 使用線程安全的API和集合類:sql

  • 使用Vector、HashTable等線程安全的集合類
  • 使用Concurrent包中提供的ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等弱一致性的集合類
  • 在Collections類中有多個靜態方法,它們能夠獲取經過同步方法封裝非同步集合而獲得的集合,如List list = Collection.synchronizedList(new ArrayList())。

4. 使用原子變量、volatile變量等
5. 使用Concurrent包中提供的信號量Semaphore、閉鎖Latch、柵欄Barrier、交換器Exchanger、Callable&Future、阻塞隊列BlockingQueue等.
6. 手動使用Lock實現基於鎖的併發控制
7. 手動使用Condition或AQS實現基於條件隊列的併發控制
8. 使用CAS和SPIN等實現非阻塞的併發控制數據庫

  

3)進程間通訊的幾種方式

1. 管道( pipe ):管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係。

2. 有名管道 (named pipe) : 有名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。

3. 信號量( semophore ) : 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。所以,主要做爲進程間以及同一進程內不一樣線程之間的同步手段。

4. 消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。

5. 信號 ( sinal ) : 信號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生。

6. 共享內存( shared memory ) :共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的 IPC 方式,它是針對其餘進程間通訊方式運行效率低而專門設計的。它每每與其餘通訊機制,如信號兩,配合使用,來實現進程間的同步和通訊。

7. 套接字( socket ) : 套解口也是一種進程間通訊機制,與其餘通訊機制不一樣的是,它可用於不一樣機器間的進程通訊。

 

 

4)ConcurrentHashMap

ConcurrentHashMap是線程安全的HashMap,內部採用分段鎖來實現,默認初始容量爲16,裝載因子爲0.75f,分段16,每一個段的HashEntry<K,V>[]大小爲2。鍵值都不能爲null。每次擴容爲原來容量的2倍,ConcurrentHashMap不會對整個容器進行擴容,而只對某個segment進行擴容。在獲取size操做的時候,不是直接把全部segment的count相加就能夠可到整個ConcurrentHashMap大小,也不是在統計size的時候把全部的segment的put, remove, clean方法所有鎖住,這種方法過低效。在累加count操做過程當中,以前累加過的count發生變化的概率很是小,全部ConcurrentHashMap的作法是先嚐試2(RETRIES_BEFORE_LOCK)次經過不鎖住Segment的方式統計各個Segment大小,若是統計的過程當中,容器的count發生了變化,再採用加鎖的方式來統計全部的Segment的大小。

 

5)ABA問題

ABA問題發生在相似這樣的場景:線程1轉變使用CAS將變量A的值替換爲C,在此時,線程2將變量的值由A替換爲C,又由C替換爲A,而後線程1執行CAS時發現變量的值仍爲A,因此CAS成功。但實際上這時的現場已經和最初的不一樣了。大多數狀況下ABA問題不會產生什麼影響。若是有特殊狀況下因爲ABA問題致使,可用採用AtomicStampedReference來解決,原理:樂觀鎖+version。能夠參考下面的案例來了解其中的不一樣

 1 public class ABAQuestion
 2 {
 3     private static AtomicInteger atomicInt = new AtomicInteger(100);
 4     private static AtomicStampedReference<Integer> atomicStampedRef = new AtomicStampedReference<Integer>(100,0);
 5  
 6     public static void main(String[] args) throws InterruptedException
 7     {
 8         Thread thread1 = new Thread(new Runnable(){
 9             @Override
10             public void run()
11             {
12                 atomicInt.compareAndSet(100, 101);
13                 atomicInt.compareAndSet(101, 100);
14             }
15         });
16  
17         Thread thread2 = new Thread(new Runnable(){
18             @Override
19             public void run()
20             {
21                 try
22                 {
23                     TimeUnit.SECONDS.sleep(1);
24                 }
25                 catch (InterruptedException e)
26                 {
27                     e.printStackTrace();
28                 }
29                 boolean c3 = atomicInt.compareAndSet(100, 101);
30                 System.out.println(c3);
31             }
32         });
33  
34         thread1.start();
35         thread2.start();
36         thread1.join();
37         thread2.join();
38  
39         Thread thread3 = new Thread(new Runnable(){
40             @Override
41             public void run()
42             {
43                 try
44                 {
45                     TimeUnit.SECONDS.sleep(1);
46                 }
47                 catch (InterruptedException e)
48                 {
49                     e.printStackTrace();
50                 }
51                 atomicStampedRef.compareAndSet(100, 101, atomicStampedRef.getStamp(), atomicStampedRef.getStamp()+1);
52                 atomicStampedRef.compareAndSet(101, 100, atomicStampedRef.getStamp(), atomicStampedRef.getStamp()+1);
53             }
54         });
55  
56         Thread thread4 = new Thread(new Runnable(){
57             @Override
58             public void run()
59             {
60                 int stamp = atomicStampedRef.getStamp();
61                 try
62                 {
63                     TimeUnit.SECONDS.sleep(2);
64                 }
65                 catch (InterruptedException e)
66                 {
67                     e.printStackTrace();
68                 }
69                 boolean c3 = atomicStampedRef.compareAndSet(100, 101, stamp, stamp+1);
70                 System.out.println(c3);
71             }
72         });
73         thread3.start();
74         thread4.start();
75     }
76 }
AtomicStampedRefrence

輸出結果:

true
false
View Code

 

 

6)servlet是線程安全的嗎

Servlet不是線程安全的。要解釋爲何Servlet爲何不是線程安全的,須要瞭解Servlet容器(即Tomcat)是如何響應HTTP請求的。

當Tomcat接收到Client的HTTP請求時,Tomcat從線程池中取出一個線程,以後找到該請求對應的Servlet對象並進行初始化,以後調用service()方法。要注意的是每個Servlet對象在Tomcat容器中只有一個實例對象,便是單例模式。若是多個HTTP請求請求的是同一個Servlet,那麼着兩個HTTP請求對應的線程將併發調用Servlet的service()方法。

 
上圖中的Thread1和Thread2調用了同一個Servlet1,因此 此時若是Servlet1中定義了實例變量或靜態變量,那麼可能會發生線程安全問題(由於全部的線程均可能使用這些變量)

好比下面的Servlet中的 name 和 i變量就會引起線程安全問題。

 

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadSafeServlet extends HttpServlet {

    public static String name = "Hello";   //靜態變量,可能發生線程安全問題
    int i;  //實例變量,可能發生線程安全問題
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("Servlet初始化");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));
        i++;
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));
        resp.getWriter().println("<html><body><h1>" + i + "</h1></body></html>");
    }
}

 



9)linux/unix下統計一行字符串出現指定字符的次數

一種方案: 先把 | 替換成換行符,wc -l 統計時候的的數量就必定是result + 1   最後把1減掉

unix系統用 sed 's/|/\n/g' 沒法替換(linux 能夠),因此考慮用tr替換

echo $(echo "10.1.4.90|15/Jan/2018:08:44:38|GET|pi.easyond/|" | tr '|' '\n' | wc -l)-1 | bc  

 

 

10)快速失敗(fail - fast)和安全失敗(fail - safe)

一 快速失敗 fail-fast

 在用迭代器遍歷一個集合對象時,若是遍歷過程當中對集合對象的內容進行了修改(增長,刪除,修改), 則會拋出 ConcurrentModificationException

原理: 迭代器在遍歷時直接訪問集合中的內容,而且在遍歷過程當中使用一個modCount變量。集合在被遍歷期間若是內容發生變化,就會改變modCount的值,每當迭代器使用hasNext()/next()遍歷下一個元素以前,都會檢測modCount變量是否爲expectedModCount值,是的話就返回遍歷,不然拋出異常,終止遍歷。

下面以AbstractList的實現舉例,其餘原理同,再也不累述

注意:這裏異常的拋出條件是檢測到this.modCount != l.modCount, 若是集合發生變化時又剛好修改了modCount的值使上述條件語句知足,那麼異常不會拋出。所以,不能依賴這個異常是否拋出的邏輯進行併發操做的編程,這個異常只建議用於檢測併發修改的bug

場景 java.util包下的集合類都是快速失敗的,不能在多線程下發生併發修改(迭代過程當中被修改)

 

二 安全失敗 fail-safe

採用安全失敗機制的集合容器,在遍歷時不是直接在集合內容上訪問的,而是先複製原有集合內容,在拷貝的集合上進行遍歷

原理: 因爲迭代時時對原集合的拷貝進行遍歷,因此在遍歷過程當中對原集合所作的修改並不能被迭代器檢測到,因此不會觸發ConcurrentModificationException

缺點: 基於拷貝內容的優勢是避免了ConcurrentModificationException,但相對地,迭代器並不能訪問到修改後的內容。即:迭代器遍歷的是開始遍歷那一刻拿到的集合拷貝,在遍歷期間原集合發生的修改迭代器無從得知。

場景: java.util.concurrent包下的容器都是安全失敗,能夠在多線程下併發使用,併發修改。

 

 

11)mysql的undo和redo

http://www.cnblogs.com/Bozh/archive/2013/03/18/2966494.html
 
 
 

12)cookie和session

http://blog.csdn.net/gavin_john/article/details/51376364
 
 

13)網站短連接生成算法

https://www.zhihu.com/question/29270034
 
 
 

14)linux下kill -9 pid強制不能殺掉進程緣由 

kill -9發送SIGKILL信號將其終止,可是如下兩種狀況不起做用:
a、該進程處於"Zombie"狀態(使用ps命令返回defunct的進程)。此時進程已經釋放全部資源,但還未獲得其父進程的確認。"zombie"進程要等到下次重啓時纔會消失,但它的存在不會影響系統性能。
b、 該進程處於"kernel mode"(核心態)且在等待不可得到的資源。處於核心態的進程忽略全部信號處理,所以對於這些一直處於核心態的進程只能經過重啓系統實現。進程在AIX 中會處於兩種狀態,即用戶態和核心態。只有處於用戶態的進程才能夠用「kill」命令將其終止。 

用top命令查看發現zombie進程數是0,看來這三個進程不屬於殭屍進程,應該是b這中狀況,就是這些進程進入核心態等待磁盤資源時出現磁盤空間不足的故障,這時我強制關閉了數據庫,因此這幾個進程就一直處於核心態沒法被殺除,看來只能重啓了。
 
 

15)給定a,b兩個文件,各存放50億個url,每一個url各佔用64字節,內存限制是4G,若是找出a,b文件共同的url

 思路:能夠估計每一個文件的大小爲5G*64=300G,遠大於4G。因此不可能將其徹底加載到內存中處理。考慮採起分而治之的方法。 遍歷文件a,對每一個url求取hash(url)%1000,而後根據所得值將url分別存儲到1000個小文件(設爲a0,a1,...a999)當中。這樣每一個小文件的大小約爲300M。遍歷文件b,採起和a相同的方法將url分別存儲到1000個小文件(b0,b1....b999)中。這樣處理後,全部可能相同的url都在對應的小文件(a0 vs b0, a1 vs b1....a999 vs b999)當中,不對應的小文件(好比a0 vs b99)不可能有相同的url。而後咱們只要求出1000對小文件中相同的url便可。 好比對於a0 vs b0,咱們能夠遍歷a0,將其中的url存儲到hash_map當中。而後遍歷b0,若是url在hash_map中,則說明此url在a和b中同時存在,保存到文件中便可。 若是分紅的小文件不均勻,致使有些小文件太大(好比大於2G),能夠考慮將這些太大的小文件再按相似的方法分紅小小文件便可

 

 

16)100億個url中的重複url已經搜索詞彙的topK問題

有一個包含100億個URL的文件,假設每一個URL佔用64B,請找出其中全部重複的URL。

將文件經過哈希函數成多個小的文件,因爲哈希函數全部重複的URL只可能在同一個文件中,在每一個文件中利用一個哈希表作次數統計。就能找到重複的URL。這時候要注意的就是給了多少內存,咱們要根據文件大小結合內存大小決定要分割多少文件

topK問題和重複URL實際上是同樣的,重複的多了纔會變成topK。其實就是在上述方法後得到全部的重複URL排個序,可是有點不必,由於咱們要找topK時,最極端的狀況也就是topK在用一個文件中,因此咱們只須要每一個文件的topK個URL,以後再進行排序,這樣就比找出所有的URL再排序好。還有一個topK個URL到最後仍是須要排序,因此咱們在找每一個文件的topK時,是否只須要找到topK個,其它順序不用管,那麼咱們就能夠用大小爲K的小根堆遍歷哈希表。這樣又能夠下降查找的時間。

 

17)如何判斷服務器須要擴容

有不少指標,最基本的好比CPU利用率,內存佔用率,網絡帶寬等。軟件層面好比QPS等。

容量設計的時候須要考慮突發流量,通常要保留20%到30%的備用容量。

集羣還要考慮災備,好比部分機器發生故障的時候接負載均衡如何正確引流限流,避免雪崩式故障(cascading failure)。

至於工具的話,要看現有的技術框架。主要的目的就是作好實時監控和預警。

18)linux下如何查看進行佔用CPU和內存的狀況

1 ps 

按內存大小排序(%MEM爲第三列,%CPU爲第二列,不在雷述)

ps -aux默認是按PID從小到大顯示的,若想按佔用內存大小排序則須要藉助另外sort命令針對第4列(內存所在列)排序:

ps -aux | sort -k4rn
 
  

咱們還能夠藉助awk來指定顯示哪幾列信息:

ps -aux |awk '{print $2, $4, $11}' | sort -k2rn | head -n 10
 
  

2 top 

在命令行提示符執行top命令.輸入大寫P,則結果按CPU佔用降序排序。輸入大寫M,結果按內存佔用降序排序

  

20)Arrays.sort() 和Collections.sort() 底層是用什麼排序

1 Arrays.sort()

public static void sort(int[] a) {
    DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}

DualPivotQuicksort翻譯過來就是雙軸快速排序,再點進去發現有這樣的判斷

if (right - left < QUICKSORT_THRESHOLD) {
    sort(a, left, right, true);
    return;
}

能夠發現若是數組的長度小於QUICKSORT_THRESHOLD的話就會使用這個雙軸快速排序,而這個值是286。

 那若是大於286,它會檢測數組的連續上升/降低的特性好很差,好的話用歸併排序,壞的話用快排

再回到上面的雙軸快速排序,點進去

sort(int[] a, int left, int right, boolean leftmost)這個方法發現
若是數據長度小於(值爲47)的話,就會用插入排序INSERTION_SORT_THRESHOLD

總結:

長度大於等於286且連續性好->歸併

長度大於等於286且連續性很差->雙軸快速排序

長度小於286且大於等於47->雙軸快速排序

長度小於47->插入排序

 

2 Collections.sort()

一路點進去發現到了Arrays類中

public static <T> void sort(T[] a, Comparator<? super T> c) {
    if (c == null) {
        sort(a);
    } else {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, 0, a.length, c, null, 0, 0);
    }
}

會發現若是LegacyMergeSort.userRequested爲true的話就會使用歸併排序,能夠經過下面代碼設置爲true

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 

不過方法legacyMergeSort的註釋上有這麼一句話,說明之後傳統歸併可能會被移除了。

/** To be removed in a future release. */

若是不爲true的話就會用一個叫TimSort的排序算法。

 

 

21)Object中有哪些方法

public方法: getClass()  hashCode()  equals()  toString()  notify()系列  wait()系列

protected方法: clone() finalize()

private方法: registerNatives, 該方法做用是將不一樣平臺c/c++實現的方法映射到java的native方法

    private static native void registerNatives();
    static {
        registerNatives();
    }

 

 

 

22)jvm GC根節點的選擇

java經過可達性分析來判斷對象是否存活,基本思想是經過一系列稱爲"GC roots"的對象做爲起始點,能夠做爲根節點的是:

(1) 虛擬機棧(棧幀中的本地變量表)中引用的對象

(2) 本地方法棧中JNI(即native方法)引用的對象

(3) 方法區中靜態屬性引用的對象

(4) 方法區中常量引用的對象

做爲GC roots的節點主要在全局性的引用(例如常量或類靜態屬性)與執行上下文(例如棧幀中的本地變量表)中。

我我的理解: 想下java內存模型的5塊,gc主要是收集堆和持久代,剛好對應棧分配的堆對象和靜態&常量所申請的持久代

 

 

23)類加載主要步驟

  • 加載 把 class 文件的二進制字節流加載到 jvm 裏面
  • 驗證 確保 class 文件的字節流包含的信息符合當前 jvm 的要求 有文件格式驗證, 元數據驗證, 字節碼驗證, 符號引用驗證等
  • 準備 正式爲類變量分配內存並設置類變量初始值的階段, 初始化爲各數據類型的零值
  • 解析 把常量值內的符號引用替換爲直接引用的過程
  • 初始化 執行類構造器()方法
  • 使用 根據相應的業務邏輯代碼使用該類
  • 卸載 類從方法區移除

 

24)Class.forName和classloader的區別

java中class.forName()和classLoader均可用來對類進行加載。
class.forName()前者除了將類的.class文件加載到jvm中以外,還會對類進行解釋,執行類中的static塊。
而classLoader只幹一件事情,就是將.class文件加載到jvm中,不會執行static中的內容,只有在newInstance纔會去執行static塊。 

 

25)獲取class類的四種方式

1.調用運行時類自己的.class屬性

Class clazz = String.class;

2,經過運行時類的對象獲取

Person p = new Person();

Class clazz = p.getClass();

3.經過Class的靜態方法獲取:體現反射的動態性

String className = 「java.util.commons」;

Class clazz = Class.forName(className);

4.經過類的加載器

String className = 「java.util.commons」;

ClassLoader classLoader = this.getClass().getClassLoader();

Class clazz = classLoader.loadClass(className);

 

 

26)String爲何是final的

final的出現是爲了避免想改變,而不想改變的理由有兩點: 設計(安全)或者效率

1 設計安全

確保不會在子類中改變語義。若是有一個String的引用,它引用的必定是一個string對象,而不多是其餘類的對象

2 效率

設計成final,jvm不用對相關方法在虛函數表中查詢,而直接定位到String類的相關方法,提升了執行效率

 一旦建立是不能被修改的。字符串對象是不可改變的,那麼它們能夠共享

 

27)kafka等mq如何保證有序性

傳統的隊列在服務器上保存有序的消息,若是多個consumers同時從這個服務器消費消息,服務器就會以消息存儲的順序向consumer分發消息。雖然服務器按順序發佈消息,可是消息是被異步的分發到各consumer上,因此當消息到達時可能已經失去了原來的順序,這意味着併發消費將致使順序錯亂。爲了不故障,這樣的消息系統一般使用「專用consumer」的概念,其實就是隻容許一個消費者消費消息,固然這就意味着失去了併發性。

在這方面Kafka作的更好,經過分區的概念,Kafka能夠在多個consumer組併發的狀況下提供較好的有序性和負載均衡。將每一個分區分只分發給一個consumer組,這樣一個分區就只被這個組的一個consumer消費,就能夠順序的消費這個分區的消息。由於有多個分區,依然能夠在多個consumer組之間進行負載均衡。注意consumer組的數量不能多於分區的數量,也就是有多少分區就容許多少併發消費。

Kafka只能保證一個分區以內消息的有序性,在不一樣的分區之間是不能夠的,這已經能夠知足大部分應用的需求。若是須要topic中全部消息的有序性,那就只能讓這個topic只有一個分區,固然也就只有一個consumer組消費它。

 

28)java對象引用方式 - 強引用,軟引用,弱引用,虛引用

從jdk1.2版本開始,把對應的引用分爲4種級別,由高到低分別爲: 強引用 > 軟引用 > 弱引用 > 虛引用.

(1) 強引用

這是最廣泛的引用。當內存空間不足時,java虛擬機寧願拋出OutOfMemoryError使程序異常終止,也不會隨意回收具備強引用的對象來解決內存不足問題

(2) 軟引用

軟引用在內存空間足夠時,垃圾回收器不會進行回收。但內存不足時就會進行回收這些對象的內存。軟引用可用來實現內存敏感的高速緩存

(3) 弱引用

具備比軟引用更短的生命週期,在垃圾回收器線程掃描它所管轄的內存區域時,一旦有弱引用,無論當前內存空間足夠與否,都會回收它的內存。不過,因爲垃圾回收器時一個優先級很低的線程,所以不必定會發現那些只具備弱引用的對象

(4)虛引用

顧名思義,就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收。

 

特別注意,在程序設計中通常不多使用弱引用與虛引用,使用軟引用的狀況較多,這是由於軟引用能夠加速JVM對垃圾內存的回收速度,能夠維護系統的運行安全,防止內存溢出(OutOfMemory)等問題的產生。

 

 

100)其餘

(2) spring中的九種設計模式:  http://ju.outofmemory.cn/entry/78206
(3) 關於MapReduce的理解?  https://www.zhihu.com/question/23345991/answer/223113502
  (5) 美團點評技術團隊-swap太高分析linux與jvm的內存關係(寫的灰常好)    http://www.importnew.com/14486.html
(6) happens-before在java源碼中的應用(CopyOnWriteArrayList & FutureTask)  http://ifeve.com/easy-happens-before/
  (7) 全局惟一自增id生成策略   http://www.javashuo.com/article/p-qchoxqve-cc.html
(8) Semaphore,能夠整理一下,沒什麼難度,主要是流量控制   https://www.jianshu.com/p/0090341c6b80
(10) hashmap1.7&1.8     http://www.importnew.com/20386.html
(12) 紅黑樹                   http://blog.csdn.net/u011240877/article/details/53329023
  (14) 刪除list的元素的各類辦法對比  http://blog.csdn.net/claram/article/details/53410175  
(15)逃逸分析   http://www.importnew.com/27262.html

(16)分類清晰的簡單面試題 https://juejin.im/entry/5838f9f1128fe1006bdaa456  

(17)tcp粘包  http://www.javashuo.com/article/p-otqxlujw-cd.html

(18)lru cache的算法實現 http://www.javashuo.com/article/p-tvkmduth-bv.html

dubbo。http://wyj.shiwuliang.com/2017/02/25/Dubbo%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%20%E2%80%94%20%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C/

(19)單點登陸sso  http://www.cnblogs.com/ywlaker/p/6113927.html

相關文章
相關標籤/搜索