1. 程式人生 > >面試總結(知乎+京東)

面試總結(知乎+京東)

知乎面試問題

一面
  • 演算法題
    兩個有序陣列,輸出第k小的數字
    思想時:分別折半查詢,每個陣列記錄自己的left,right索引,進行查詢。
  • hashmap
    • 原始碼結構
    • hashmap在擴容時空間建立+新舊節點的對應關係+如果擴容過程中查詢該怎麼查詢**(分析如下)**
      • 究竟哪些節點需要申請新的儲存空間?哪些不需要呢?
        • 需要新申請空間的節點:newTab,即為新table陣列,申請空間個數為32、64、128等。
        • 不需要新申請空間的節點:所有連結串列或者紅黑樹上的節點;
        • 原始碼:resize()方法
          Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
      • 新舊索引有什麼關係?
        • 因為我們使用的增長策略是2的整數次冪方式,table的容量在更改時,同一元素在table中的索引要麼不變,要麼移動到相對原位置而言距離2的整數次冪的一個位置。
        • 舊連結串列中的節點如何對應到新的table索引中?
          思想:對這個舊連結串列進行遍歷,從而先生成兩個連結串列;然後一個放在原來索引位置j處,一個放在[j+oldCap]處;
        • 那麼生成兩個連結串列的策略是怎樣的呢?
          if ((e.hash & oldCap) == 0) 條件成立的節點是放在原來索引位置j處的連結串列;
          否則,放在j+oldCap索引處的連結串列;
      • 查詢引數包括:hash(key)和key。那麼接下來如何進行查詢?
        • 先獲得first節點的索引,其索引策略是:
          first = tab[(n - 1) & hash]
        • 接下來如果first節點為紅黑樹節點,則按照紅黑樹查詢方式查詢;
        • 如果first節點為連結串列節點,則按照連結串列查詢方式進行查詢;
        • 那麼問題來了,如果此時hashMap在擴容,那麼tab究竟是新tab陣列還是舊tab陣列?
          通過resize()方法的原始碼可以發現,有這樣一步操作:
          Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
          table = newTab;
          並且這步操作的後面,才會發生生成新的兩個連結串列的操作。所以如果hashMap擴容過程中發生查詢操作,則在table沒有被重新賦值前就在舊table中查詢;否則在新table中查詢;但在新table的查詢中,可能新的2個連結串列還沒有生成導致存在的元素查詢結果也是null;不過本來hashMap也是執行緒不安全的,返回併發導致的錯誤結果也能理解。
  • jvm記憶體模型+gc演算法
  • mysql索引實現
  • B樹和B+樹的對比
  • LRU cache的實現方式?自己說了連結串列方式,不知道還有什麼方式
    • LinkedHashMap的實現方式
      • 一個包含3個指標節點的雙向連結串列。節點指標為before,next,after。分別指向:
        雙向連結串列的前一個節點;
        hash值衝突的邏輯連結串列;
        雙向連結串列的後一個節點;
        參考:https://blog.csdn.net/caoxiaohong1005/article/details/79909083
      • 時間複雜度
        • get時,最好O(1),最差O(N);
        • put時,最好O(1),最差O(N);
      • 空間複雜度
        O(N)
    • 單鏈表+hashmap
      • 底層使用有頭指標的單鏈表,同時用hashmap對每個key維護一個前驅節點;
      • 時間複雜度
        • get時,首先從hashmap中找到對應的節點,然後移到頭節點,並更改hashmap的對映關係;
        • set時,如果cache未滿,則直接插入到頭節點前面,並更改hashmap的對映關係;
        • set時,如果cache滿了,則將重用連結串列尾節點,然後挪到表頭,並更改hashmap的對映關係;
      • 空間複雜度
        O(N)
  • 網路程式設計socket,自己說不會也就沒有再問
  • TCP/IP 的三次握手和四次揮手過程
二面
  • 講解實習專案架構和自己實現的模組功能

  • springAOP的實現原理

    • java動態代理可以對類實現嗎?不知道,只知道是對interface的實現
    • java動態原理
      • 使用到的class和interface包括:Proxy類和invocationHandler介面。

      • 需要自己寫的class和interface
        1)被代理物件的interface
        2)被代理物件的interfaceImpl
        3)動態代理的InvocationHandler實現類

      • JVM生成動態代理類
        傳入引數:定義代理類的類載入器,代理類要實現的介面列表,invocationHandler例項

          import java.lang.reflect.InvocationHandler;
          import java.lang.reflect.Method;
          import java.lang.reflect.Proxy;
        
          /**
           * @Author: cxh
           * @CreateTime: 18/9/23 00:48
           * @ProjectName: JavaBaseTest
           */
          public class AopTest {
          	public static void main(String[] args) {
          	//定義被代理物件
          	Subject subjectImpl = new SubjectImpl();
          	//定義InvocationHandler介面例項
          	InvocationHandler invocationHandler = new InvocationHandlerImpl(subjectImpl);
          	//生成動態代理例項(定義代理類的類載入器,代理類要實現的介面列表,invocationHandler例項)
          	Subject subject = (Subject) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(), subjectImpl.getClass().getInterfaces(), invocationHandler);
        
          	System.out.println("subject.getClass().getName():" + subject.getClass().getName());
          	subject.before();
          	}
          }
        
          /**
           *被代理物件的介面
           */
          interface Subject {
          void before();
        
          void after();
          }
        
          /**
          * 被代理物件
          */
          class SubjectImpl implements Subject {
        
          	@Override
          	public void before() {
          		System.out.println("this is method of before().");
          	}
        
          	@Override
          	public void after() {
          		System.out.println("this is method of after().");
          	}
          }
        
          /**
          * 動態代理,必須實現InvocationHandler介面
          */
          class InvocationHandlerImpl implements InvocationHandler {
        
          	Subject subject;
        
          	/**
          	 * 建構函式引數必須包括:被代理物件,這樣呼叫動態代理的invoke()方法時,才會呼叫被代理物件的方法.
          	*/
          	InvocationHandlerImpl(Subject subject) {
          		this.subject = subject;
          	}
        
          	@Override
          		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          			System.out.println("before invoke()");
          			System.out.println("the  method is :" + method);
          			method.invoke(subject, args);
          			System.out.println("after invoke()");
        
          			return null;
          		}
          }  
           
          -----------   
          輸出結果:  
          subject.getClass().getName():$Proxy0
          before invoke()
          the  method is :public abstract void Subject.before()
          this is method of before().
          after invoke()
        
  • springIOC的實現原理 :三級快取+提前曝光+java的物件引用原理

    • Spring迴圈依賴的理論依據其實是Java基於引用傳遞,當我們獲取到物件的引用時,物件的field或者或屬性是可以延後設定的。Spring單例物件的初始化其實可以分為三步:
      • createBeanInstance, 例項化,實際上就是呼叫對應的構造方法構造物件,此時只是呼叫了構造方法,spring xml中指定的property並沒有進行populate。
      • populateBean,填充屬性,這步對spring xml中指定的property進行populate
      • initializeBean,呼叫spring xml中指定的init方法,或者AfterPropertiesSet方法
        會發生迴圈依賴的步驟集中在第一步和第二步。
    • spring在解決迴圈依賴中使用了三級快取
      • 單例物件的cache:
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
      • 單例物件工廠的cache:
        private final Map <String, ObjectFactory?> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
      • 提前曝光的單例物件的cache:
        private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    • singleton初始化過程圖片:
      在這裡插入圖片描述
    • 顯然:兩個迴圈依賴都是通過構造器函式進行依賴的,則spring無法解決此種依賴。因為提前暴露出來的原始bean需要執行完例項構造器函式。
  • interface 和 abstractclass 的區分和適用場景

    • 區別
      • 變數型別:抽象類中的成員變數可以是各種型別的,但是介面中的只能是public static final型別的。
      • 單根繼承:一個類只能繼承一個抽象類,但可以實現多個介面;
      • 實現關鍵字:介面需要實現implements;而抽象類需要繼承extends;
      • 強調內容:interface強調特定功能的實現;abstract class強調所屬關係;
    • 使用場景
      • 介面:
        • 如果想實現多繼承,則使用介面;
        • 用於定義mix-in型別,表示類具有某特定效能,如Serializable介面,沒有任何方法,只是用於表示實現該介面的類可以序列化,當然序列話方法要自己寫程式碼去實現。
      • 抽象類:
        • 如果基本功能不斷改變,則用抽象類。因為不斷改變功能時,用介面的話,就要改變所有實現了該介面的類。
        • 某些場合下,只靠純粹的介面不能滿足類與類之間的協調,還必需類中表示狀態的變數來區別不同的關係。abstract的中介作用可以很好地滿足這一點.

京東面試總結

一面
  • 演算法題
  • 實習專案
  • 資料庫為什麼要使用執行緒池
    • 原因:各種池其實原因都一樣
      • 實現方式:
        預先建立一定數量的執行緒,當有請求達到時,執行緒池分配一個執行緒提供服務,請求結束後,該執行緒又去服務其他請求。
      • 優勢
        1)避免了執行緒和記憶體物件的頻繁建立和釋放
        2)降低了服務端的併發度
        3)減少了上下文切換和資源的競爭,提高資源利用效率
    • MySQL的執行緒池改進過程
      1)One-Connection-Per-Thread
      每一個數據庫連線,Mysql-Server都會建立一個獨立的執行緒服務,請求結束後,銷燬執行緒。
      2)基於1)的thread-cache,將執行緒快取起來,以供下次使用,避免頻繁建立和釋放的問題,但是無法解決高連線數的問題。1)的方式隨著連線數暴增,導致需要建立同樣多的服務執行緒,高併發執行緒意味著高的記憶體消耗,更多的上下文切換(cpu cache命中率降低)以及更多的資源競爭,導致服務出現抖動。
      3)Thread-Pool實現方式
      1.執行緒處理的最小單位是statement(語句),一個執行緒可以處理多個連線的請求。
      2.在保證充分利用硬體資源情況下(合理設定執行緒池大小),可以避免瞬間連線數暴增導致的伺服器抖動。
    • 執行緒池常配置的屬性
      1)user和password
      2)initialPoolSize、minPoolSize、maxPoolSize
      3)acquireIncrement :聲明當連線池中連線耗盡時再一次新生成多少個連線,預設為3個
      4)maxIdleTime :超過多長時間連線自動銷燬,預設為0,即永遠不會自動銷燬
      5)maxStatements :JDBC的標準引數,用以控制資料來源內載入的PreparedStatements數量
      ps:但由於預快取的statements屬於單個connection而不是整個連線池。所以設定這個引數需要考慮到多方面的因素。
      如果maxStatements與maxStatementsPerConnection均為0,則快取被關閉
      6)idleConnectionTestPeriod :每xx秒檢查所有連線池中的空閒連線
    • 執行緒池和連線池
      • 執行緒池
      1. 執行緒池實現在server端,通過建立一定數量的執行緒服務DB請求
      2. 執行緒池服務的最小單位是語句,即一個執行緒可以對應多個活躍的連線
      3. 可以將server端的服務執行緒數控制在一定的範圍,減少了系統資源的競爭和執行緒上下文切換帶來的消耗,同時也避免出現高連線數導致的高併發問題
      • 連線池
        1)連線池通常實現在Client端,是指應用(客戶端)建立預先建立一定的連線,利用這些連線服務於客戶端所有的DB請求
        2)如果某一個時刻,空閒的連線數小於DB的請求數,則需要將請求排隊,等待空閒連線處理。通過連線池可以複用連線,避免連線的頻繁建立和釋放,從而減少請求的平均響應時間,並且在請求繁忙時,通過請求排隊,可以緩衝應用對DB的衝擊
        PS:連線池和執行緒池相輔相成,通過連線池可以減少連線的建立和釋放,提高請求的平均響應時間,並能很好地控制一個應用的DB連線數,但無法控制整個應用叢集的連線數規模,從而導致高連線數,通過執行緒池則可以很好地應對高連線數,保證server端能提供穩定的服務。
  • 畢設+神經網路
  • java實現檔案的匯入匯出用到的類有哪些?
    只記得InputStream,OutputStream.
  • java如何實現將一個Date按照某種日期的格式顯示?
    SimpleDateFormat可以實現
二面
  • 講實習專案

  • Spring的功能有哪些
    自己從spring組成,和各個模組及常用模組的功能都講了一遍

  • Spring事務的隔離級別

    • Spring事務的隔離級別和MySQL的事務隔離級別的關係
      • Spring使用的事務隔離級別必須是MySQL能支援的,故如果Spring設定的隔離級別MySQL不支援則此Spring的設定無效。
      • 如果Spring和MySQL設定了不同的隔離級別,那麼以Spring會在事務開始時,根據你程式中設定的隔離級別,調整資料庫隔離級別與你的設定一致。
  • Mybatis的二級快取

    • 一級快取
      • 生命週期:基於sqlSession
    • 二級快取
      • 生命週期:基於application
      • 作用範圍:按照每個namepace一個快取來存貯和維護,同一個namespace放到一個快取物件中。
    • cache使用的注意事項
      • 只能在【只有單表操作】的表上使用快取
        不只是要保證這個表在整個系統中只有單表操作,而且和該表有關的全部操作必須全部在一個namespace下。
      • 在可以保證查詢遠遠大於insert,update,delete操作的情況下使用快取
    • 避免使用二級快取
      多表操作不管多表操作寫到哪個namespace下,都會存在某個表不在這個namespace下的情況,這會導致查詢使用快取的時候結果就是錯的。
  • MySQL的索引建立原則
    自己先說了索引型別,不同引擎支援的索引型別,以及索引的使用規則

  • java中的鎖怎麼實現的
    自己講了volatile,synchronized的實現原理,以及從jdk1.6開始synchronized對鎖的處理:偏向鎖,輕量級鎖,重量級鎖。以及鎖只能升級不能降級。

  • java反射都用過什麼?