天天看點

2020騰訊面試題!附答案

一面:

集合有哪些:

List(ArrayList Linklist ) set(Set Treeset Hashset) map(Hashmap currentHashmap hashtable )

2020騰訊面試題!附答案

arraylist和linkedlist差別

一個是基于數組的實作 一個是基于的連結清單的實作

hashmap怎麼擴容(多線程擴容為什麼會死循環),put過程

出現的是連結清單的閉環。

2020騰訊面試題!附答案

concurrentHashMap 1.7和1.8

1.7是采用采用的還是分段鎖的機制 1.8采用的是CAS機制來實作的。

接口和抽象類差別

JVM記憶體分區

2020騰訊面試題!附答案

新生代:

eden,survivor_from, survivor_to

垃圾回收算法:

三種 标記清除 複制算法 标記整理算法

PretenureSizeThreshold,maxTenuringThreshold(預設15)

如果并發的線程數量很多,并且每個線程都是執行一個時間很短的任務就結束了,這樣頻繁建立線程就會大大降低系統的效率,因為頻繁建立線程和銷毀線程需要時間。

1線程池狀态

在ThreadPoolExecutor中定義了一個volatile變量,另外定義了幾個static final變量表示線程池的各個狀态:

volatile int runState;

static final int RUNNING = 0;

static final int SHUTDOWN = 1;

static final int STOP = 2;

static final int TERMINATED = 3;

runState表示目前線程池的狀态,它是一個volatile變量用來保證線程之間的可見性;

下面的幾個static final變量表示runState可能的幾個取值。

當建立線程池後,初始時,線程池處于RUNNING狀态;

如果調用了shutdown()方法,則線程池處于SHUTDOWN狀态,此時線程池不能夠接受新的任務,它會等待所有任務執行完畢;

如果調用了shutdownNow()方法,則線程池處于STOP狀态,此時線程池不能接受新的任務,并且會去嘗試終止正在執行的任務;

當線程池處于SHUTDOWN或STOP狀态,并且所有工作線程已經銷毀,任務緩存隊列已經清空或執行結束後,線程池被設定為TERMINATED狀态。

2任務的執行

ThreadPoolExecutor類中其他的一些比較重要成員變量:

rivate final BlockingQueue<Runnable> workQueue; //任務緩存隊列,用來存放等待執行的任務

private final ReentrantLock mainLock = new ReentrantLock(); //線程池的主要狀态鎖,對線程池狀态(比如線程池大小//、runState等)的改變都要使用這個鎖

private final HashSet<Worker> workers = new HashSet<Worker>(); //用來存放工作集

private volatile long keepAliveTime; //線程存貨時間

private volatile boolean allowCoreThreadTimeOut//是否允許為核心線程設定存活時間

private volatile int corePoolSize; //核心池的大小(即線程池中的線程數目大于這個參數時,送出的任務會被放進任務緩存隊列)

private volatile int maximumPoolSize; //線程池最大能容忍的線程數

private volatile int poolSize; //線程池中目前的線程數

private volatile RejectedExecutionHandler handler; //任務拒絕政策

private volatile ThreadFactory threadFactory; //線程工廠,用來建立線程

private int largestPoolSize; //用來記錄線程池中曾經出現過的最大線程數

private long completedTaskCount; //用來記錄已經執行完畢的任務個數

1)首先,要清楚corePoolSize和maximumPoolSize的含義;

2)其次,要知道Worker是用來起到什麼作用的;

3)要知道任務送出給線程池之後的處理政策,這裡總結一下主要有4點:

如果目前線程池中的線程數目小于corePoolSize,則每來一個任務,就會建立一個線程去執行這個任務;

如果目前線程池中的線程數目>=corePoolSize,則每來一個任務,會嘗試将其添加到任務緩存隊列當中,若添加成功,則該任務會等待空閑線程将其取出去執行;若添加失敗(一般來說是任務緩存隊列已滿),則會嘗試建立新的線程去執行這個任務;

如果目前線程池中的線程數目達到maximumPoolSize,則會采取任務拒絕政策進行處理;

如果線程池中的線程數量大于 corePoolSize時,如果某線程空閑時間超過keepAliveTime,線程将被終止,直至線程池中的線程數目不大于corePoolSize;如果允許為核心池中的線程設定存活時間,那麼核心池中的線程空閑時間超過keepAliveTime,線程也會被終止。

3線程池中的線程初始化

預設情況下,建立線程池之後,線程池中是沒有線程的,需要送出任務之後才會建立線程。

4任務緩存隊列及排隊政策

在前面我們多次提到了任務緩存隊列,即workQueue,它用來存放等待執行的任務

5任務拒絕政策

當線程池的任務緩存隊列已滿并且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕政策,通常有以下四種政策:

ThreadPoolExecutor.AbortPolicy:丢棄任務并抛出RejectedExecutionException異常。

ThreadPoolExecutor.DiscardPolicy:也是丢棄任務,但是不抛出異常。

ThreadPoolExecutor.DiscardOldestPolicy:丢棄隊列最前面的任務,然後重新嘗試執行任務(重複此過程)

ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務

6線程池的關閉

ThreadPoolExecutor提供了兩個方法,用于線程池的關閉,分别是shutdown()和shutdownNow(),其中:

shutdown():不會立即終止線程池,而是要等所有任務緩存隊列中的任務都執行完後才終止,但再也不會接受新的任務

shutdownNow():立即終止線程池,并嘗試打斷正在執行的任務,并且清空任務緩存隊列,傳回尚未執行的任務

7線程池容量的動态調整

ThreadPoolExecutor提供了動态調整線程池容量大小的方法:setCorePoolSize()和setMaximumPoolSize(),

setCorePoolSize:設定核心池大小

setMaximumPoolSize:設定線程池最大能建立的線程數目大小

當上述參數從小變大時,ThreadPoolExecutor進行線程指派,還可能立即建立新的線程來執行任務。

2020騰訊面試題!附答案

如果是不采用是這個那就在隊列中的線程是不可能出隊列的,就是如果是的非公平的鎖的話那就永遠不能出隊列。那可能能執行不到該線程。

JVM調優(不太會)

Xms2g:初始化推大小為 2g;

-Xmx2g:堆最大記憶體為 2g;

-XX:NewRatio=4:設定年輕的和老年代的記憶體比例為 1:4;

-XX:SurvivorRatio=8:設定新生代 Eden 和 Survivor 比例為 8:2;

–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器組合;

-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器組合;

-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器組合;

-XX:+PrintGC:開啟列印 gc 資訊;

-XX:+PrintGCDetails:列印 gc 詳細資訊。

如何判斷對象是否應該被回收(引用計數法,可達性分析)

root根包括哪些:對象頭

CMS回收過程,優缺點

并行收集垃圾

2020騰訊面試題!附答案

初始标記:隻是标記一下 GC Roots 能直接關聯的對象,速度很快,仍然需要暫停所有的工作線程。

并發标記:進行 GC Roots 跟蹤的過程,和使用者線程一起工作,不需要暫停工作線程。

重新标記:為了修正在并發标記期間,因使用者程式繼續運作而導緻标記産生變動的那一部分對象的标記記錄,仍然需要暫停所有的工作線程。

并發清除:清除 GC Roots 不可達對象,和使用者線程一起工作,不需要暫停工作線程。由于耗時最長的并發标記和并發清除過程中,垃圾收集線程可以和使用者現在一起并發工作, 是以總體上來看CMS 收集器的記憶體回收和使用者線程是一起并發地執行:

G1回收過程

2020騰訊面試題!附答案

類加載過程(加載,驗證,準備,解析,初始化)

2020騰訊面試題!附答案

雙親委派優點

2020騰訊面試題!附答案

=

七層模型

實體層 資料鍊路層 網絡層 傳輸層 表示層 應用層 會話層

2020騰訊面試題!附答案

四次揮手過程(中間狀态也要答)

HttpTCP 在傳輸之前會進行三次溝通,一般稱為“三次握手”,傳完資料斷開的時候要進行四次溝通,一般稱為“四次揮手”。(就是Http的連接配接和斷開的模式)

2020騰訊面試題!附答案

第一次握手:主機 A 發送位碼為 syn=1,随機産生 seq number=1234567 的資料包到伺服器,主機 B由 SYN=1 知道, A 要求建立聯機;

第 二 次 握 手 : 主 機 B 收 到 請 求 後 要 确 認 聯 機 信 息 , 向 A 發 送 ack number=( 主 機 A 的seq+1),syn=1,ack=1,随機産生 seq=7654321 的包

第三次握手: 主機 A 收到後檢查 ack number 是否正确,即第一次發送的 seq number+1,以及位碼ack 是否為 1,若正确, 主機 A 會再發送 ack number=(主機 B 的 seq+1),ack=1,主機 B 收到後确認。

四次揮手:

2020騰訊面試題!附答案

TCP 建立連接配接要進行三次握手,而斷開連接配接要進行四次。這是由于 TCP 的半關閉造成的。因為 TCP 連接配接是全雙工的(即資料可在兩個方向上同時傳遞)是以進行關閉時每個方向上都要單獨進行關閉。這個單方向的關閉就叫半關閉。當一方完成它的資料發送任務,就發送一個 FIN 來向另一方通告将要終止這個方向的連接配接。

1關閉用戶端到伺服器的連接配接:首先用戶端 A 發送一個 FIN,用來關閉客戶到伺服器的資料傳送,然後等待伺服器的确認。其中終止标志位 FIN=1,序列号 seq=u

2伺服器收到這個 FIN,它發回一個 ACK,确認号 ack 為收到的序号加 1。

3關閉伺服器到用戶端的連接配接:也是發送一個 FIN 給用戶端。

4客戶段收到 FIN 後,并發回一個 ACK 封包确認,并将确認序号 seq 設定為收到序号加 1。

首先進行關閉的一方将執行主動關閉,而另一方執行被動關閉。

為什麼TCP能保證不丢失

(滑動視窗,擁塞控制)

HTTP和HTTPS的差別

2020騰訊面試題!附答案

GET和POST差別

安全性:get 不安全 post 相對安全

傳輸的大小:get的傳輸較小 POST的傳輸較大

資料的來源範式Get是從伺服器上獲得資料,而Post則是向伺服器傳遞資料的。

mysql全家桶又來了,索引資料結構

采用是B+樹,B+的設計底層資料結構和相關的索引的知識。

為什麼用B+樹而不用hash和B-Tree

二叉樹(可能出現全部在左邊和右邊的資料)——>AVL(平衡二叉樹資料大量的時候平衡的時間太多,)——>B Tree(多路平衡查找樹)(資料表中的資料都是存儲在頁中的,是以一個頁中能存儲多少行資料呢指針少的情況下要儲存大量資料,隻能增加樹的高度,導緻IO操作變多,查詢性能變低)——>B+ Tree的一個演變的過程來進行分析,為什麼使用B+ Tree的?B+ Tree,都放在了葉子節點上。提高了檢索的效率。預讀原理,因為B+ Tree無 data 域,其實就是因為沒有date域了,但是每次IO的頁的大小是固定的,每次IO讀取若幹個塊塊中包含的Key域的值肯定更多啊,B+樹單次磁盤IO的資訊量大于B樹,從這點來看B+樹相對B樹磁盤 IO 次數少。利用了磁盤預讀原理,将一個節點的大小設為等于一個頁,這樣每個節點隻需要一次I/O就可以完全載入。1、B+Tree中因為資料都在葉子節點,是以每次查詢的時間複雜度是固定的,因為穩定性保證了2、而且葉子節點之間都是連結清單的結構,是以B+Tree也是可以支援範圍查詢的,而B樹每個節點 key 和 data 在一起,則無法區間查找。

InooDB和MyISAM的差別(事務,聚集索引,鎖的粒度等)

2020騰訊面試題!附答案

回表,聯合索引查詢會不會用到索引系列問題

下面我們來假設一種情況,一個表有三個字段 ID ,name ,age,我将ID設定成主鍵索引,name設成輔助索引。然後來看一下下面的sql:

1.select * from t where id='5';

2.select * from t where name='張三';

兩個很簡單的Sql,第一個sql不用說,直接通過主鍵索引,從樹上直接可以得到結果,那第二個sql:首先name,mysql并不能得到所有列的資訊(也就是 ),他隻能得到主鍵ID,然後他會根據ID在進行二次查詢,這就引發了--回表問題。這就是為啥不能使用 的原因。那麼怎麼解決那:第一不要寫*,第二利用組合索引,也就是說你根據業務實際需要,将需要的字段形成組合索引。

是以是會用到的索引的。

最左比對是什麼意思,聯合索引建立索引過程

在Mysql建立多列索引(聯合索引)有最左字首的原則,即最左優先。假設我們有兩列a,b,a和b是聯合索引,他的順序是a,b,我們在where語句中調用a=? and b=?的時候就會走聯合索引,如果調用where a = ?的時候也會走索引,但是當我們使用where b = ?的時候就不會走這個聯合索引。

成因:mysql建立複合索引的規則是首先會對複合索引的最左邊,也就是索引中的第一個字段進行排序,在第一個字段排序的基礎上,在對索引上第二個字段進行排序,其實就像是實作類似order by 字段1,字段2這樣的排序規則,那麼第一個字段是絕對有序的,而第二個字段就是無序的了,是以一般情況下直接隻用第二個字段判斷是用不到索引的,這就是為什麼mysql要強調聯合索引最左比對原則的原因。

獨占所,共享鎖,樂觀鎖講一下

寫鎖是獨占鎖 ,在這個期間是不允許的任何線程來操作對象的。 讀鎖就是共享鎖,可以使讓其他線程的來讀取的,但是不允許有修改。樂觀鎖是共享鎖的一種,在通過樂觀鎖的時候擷取對象的時候先比較一下樂觀鎖的版本号。如果版本号是正确的,那就可以擷取對象。如果是版本不對的話。那就是不允許修改的。

mysql分庫分表?

垂直拆分

垂直分庫是根據資料庫裡面的資料表的相關性進行拆分,比如:一個資料庫裡面既存在使用者資料,又存在訂單資料,那麼垂直拆分可以把使用者資料放到使用者庫、把訂單資料放到訂單庫。垂直分表是對資料表進行垂直拆分的一種方式,常見的是把一個多字段的大表按常用字段和非常用字段進行拆分,每個表裡面的資料記錄數一般情況下是相同的,隻是字段不一樣,使用主鍵關聯

垂直拆分的優點是:

可以使得行資料變小,一個資料塊(Block)就能存放更多的資料,在查詢時就會減少I/O次數(每次查詢時讀取的Block 就少)

可以達到最大化利用Cache的目的,具體在垂直拆分的時候可以将不常變的字段放一起,将經常改變的放一起

資料維護簡單

垂直拆分缺點是:

主鍵出現備援,需要管理備援列

會引起表連接配接JOIN操作(增加CPU開銷)可以通過在業務伺服器上進行join減少資料庫壓力

依然存在單表資料量過大的問題(需要水準拆分)

事務處理複雜

水準拆分

水準拆分是通過某種政策将資料分片來存儲,分庫内分表和分庫兩部分,每片資料會分散到不同的MySQL表或庫,達到分布式的效果,能夠支援非常大的資料量。前面的表分區本質上也是一種特殊的庫内分表 庫内分表,僅僅是單純的解決了單一表資料過大的問題,由于沒有把表的資料分布到不同的機器上,是以對于減輕MySQL伺服器的壓力來說,并沒有太大的作用,大家還是競争同一個實體機上的IO、CPU、網絡,這個就要通過分庫來解決

水準拆分的優點是:

不存在單庫大資料和高并發的性能瓶頸

應用端改造較少

提高了系統的穩定性和負載能力

缺點是:

分片事務一緻性難以解決

跨節點Join性能差,邏輯複雜

資料多次擴充難度跟維護量極大

分片原則

能不分就不分,參考單表優化

分片數量盡量少,分片盡量均勻分布在多個資料結點上,因為一個查詢SQL跨分片越多,則總體性能越差,雖然要好于所有資料在一個分片的結果,在必要的時候進行擴容,增加分片數量

分片規則需要慎重選擇做好提前規劃,分片規則的選擇,需要考慮資料的增長模式,資料的通路模式,分片關聯性問題,以及分片擴容問題,最近的分片政策為範圍分片,枚舉分片,一緻性Hash分片,這幾種分片都有利于擴容

盡量不要在一個事務中的SQL跨越多個分片,分布式事務一直是個不好處理的問題

查詢條件盡量優化,盡量避免Select * 的方式,大量資料結果集下,會消耗大量帶寬和CPU資源,查詢盡量避免傳回大量結果集,并且盡量為頻繁使用的查詢語句建立索引。

通過資料備援和表分區賴降低跨庫Join的可能。

這裡特别強調一下分片規則的選擇問題,如果某個表的資料有明顯的時間特征,比如訂單、交易記錄等,則他們通常比較合适用時間範圍分片,因為具有時效性的資料,我們往往關注其近期的資料,查詢條件中往往帶有時間字段進行過濾,比較好的方案是,目前活躍的資料,采用跨度比較短的時間段進行分片,而曆史性的資料,則采用比較長的跨度存儲。

總體上來說,分片的選擇是取決于最頻繁的查詢SQL的條件,因為不帶任何Where語句的查詢SQL,會周遊所有的分片,性能相對最差,是以這種SQL越多,對系統的影響越大,是以我們要盡量避免這種SQL的産生。

sql優化

1字段的優化

2查詢的優化

3索引的優化

4讀寫分離

5分庫分表的操作

6資料庫叢集的操作

線程和程序概念(共享哪些區域)

1.堆

幾乎所有對象執行個體被配置設定到這裡,也是垃圾收集器管理的主要區域。Java堆可以被分為新生代和老生代。進一步劃分,則有Eden空間、From Survivor空間、To Survivor空間等。無論如何劃分,都是為了更好地回收記憶體、更快的配置設定記憶體。

方法區

方法區由于存儲虛拟機加載的類的資訊、常量、靜态變量、JIT編譯後的代碼等。

虛拟記憶體講一下(分頁)

synchronized和Lock的差別

一個是通過指令集來實作鎖住的對象的頭來實作加鎖的。

一個是通過設定一個标志位置來鎖住獨享的。

volatile的作用

JMM記憶體模型和緩存一緻性協定還有就是的一個是保持可見性的

算法題:存儲有[0,n)的數組,數組長度為len。隻能交換數組裡n和0的位置進行排序

/查詢學生表中姓名、學号,并以學号降序排序/

select name,StuID from Students_information order by StuID desc /*order by 以什麼排序,預設為升序,desc是降序/

/查詢學生表中前5名學生的姓名,學号,并以學号升序排列/

select top 5 name,StuID from Students_information order by StuID /order by 預設為升序/

二面:

項目問題10分鐘,問到了Hash沖突

利用是數組+連結清單來解決hash沖突

synchronized底層實作(markWord,entrySet,waitSet)

通過鎖住對象的頭部來實作對對象加鎖,synchronize的關鍵字在以前是使用的指令來實作的

他屬于獨占式的悲觀鎖,同時屬于可重入鎖。代碼塊同步是使用monitorenter和monitorexit指令實作的。monitorenter指令是在編譯後插入到同步代碼塊的開始位置,而monitorexit是插入到方法結束處和異常處,JVM要保證每個monitorenter必須有對應的monitorexit與之配對任何對象都有一個monitor與之關聯,當且一個monitor被持有後,它将處于鎖定狀态。

在Java中,鎖共有4種狀态,級别從低到高依次為:無狀态鎖,偏向鎖,輕量級鎖和重量級鎖狀态,這幾個狀态會随着競争情況逐漸更新。鎖可以更新但不能降級。?通過一個标志位來判斷 兩個位置00表示的4種鎖

AQS底層實作(非公平鎖,公平鎖)

底層采用的是雙連結清單的來實作了的,公共鎖的定義是所有的對象在擷取鎖的時候都是需要進入隊列的。非公平鎖是在對象擷取鎖的時候是采用是首先檢視鎖是否為空,如果是空的話,那就可以對擷取,如果是有對象持有的話,那就進入隊列進行排隊。

Spring ICO,AOP介紹

SpringIOC是spring對提供了對類的全生命周期的管理的一種思想,利用反射機制來實作的對Bean的執行個體化産生和建立和銷毀這樣的機制。來實作對類對的屬性的控制,這個過程中Bean執行個體和生命周期是SpringIOC中最重要的。Spring的Bean産生詳細請見其他。

SpringAOP是一種切向程式設計的思想。在傳統的過程時候由于是在傳統的架構中都是垂直的流程體系。但是在這個過程中經常産生一些橫向問題,比如log日志記錄,權限驗證,事務處理,性能檢查的問題,為了遵循軟體的開閉原則。就是對原來不修改進而擴充原累的方法和功能。SpringAOP就是實作了這樣一種思想。通過對原方法和類在不修改代碼的情況下而進行了類的增強的方式。

Spring用到了什麼設計模式

工廠模式:BeanFactory就是簡單工廠模式的展現,用來建立對象的執行個體;

單例模式:Bean預設為單例模式。

代理模式:Spring的AOP功能用到了JDK的動态代理和CGLIB位元組碼生成技術;

模闆方法:用來解決代碼重複的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。

觀察者模式:定義對象鍵一種一對多的依賴關系,當一個對象的狀态發生改變時,所有依賴于它的對象都會得到通知被制動更新,如Spring中listener的實作–ApplicationListener。

單例為什麼加鎖,volatile什麼作用

單例模式中有一種是懶漢模式。這樣的模式是會産生的線程安全的問題。volatile是讓變量在多線程的情況下保持對其他線程的可見。

hashmap什麼時候用到了紅黑樹

當連結清單的節點超過8個時候采用紅黑樹來實作存儲。

介紹紅黑樹特點,為什麼不用AVL樹

紅黑樹屬于平衡二叉樹。它不嚴格是因為它不是嚴格控制左、右子樹高度或節點數之差小于等于1,但紅黑樹高度依然是平均log(n),且最壞情況高度不會超過2log(n)。紅黑樹的插入效率比AVL的數要高。

紅黑樹不追求"完全平衡",即不像AVL那樣要求節點的 |balFact| <= 1,它隻要求部分達到平衡,但是提出了為節點增加顔色,紅黑是用非嚴格的平衡來換取增删節點時候旋轉次數的降低,任何不平衡都會在三次旋轉之内解決,而AVL是嚴格平衡樹,是以在增加或者删除節點的時候,根據不同情況,旋轉的次數比紅黑樹要多

算法題:一個連結清單:奇數序号升序,偶數序号降序,要求做這個連結清單的整體升序排序

private static ListNode[] splitList(ListNode head) {

ListNode cur = head;

}

private static ListNode reverseList(ListNode head) {

ListNode pre = null;

private static ListNode mergeLists(ListNode head1, ListNode head2) {

if (head1 == null && head2 == null) {

return null;

三面:

介紹了兩個項目

怎麼解決超賣(答:redis + mysql樂觀鎖)

職業規劃 + 想成為tech lead應該應該具備什麼條件

現在有哪些offer

繼續閱讀