基礎篇
1、談談多態,及多態的好處
多態,父類引用指向子類。
當把不同的子類對象都當做父類類型來看待,可以屏蔽不同子類對象之間的實現差異,從而寫出通用的代碼達到通用編程,以適應需求的不斷變化。
在實際開發中,父類類型作爲方法形式參數,傳遞子類對象給方法,進行方法的調用,更能體現出多態的拓展性和便利
方便代碼維護和拓展
2、談談繼承,繼承得好處
從上層往下層看,當定義類B時,如果類A有和B相同的內容,且A和B屬於同一類型,這是B就可繼承自A
從下層往上層看,當定義的多個類屬於同一類型,且有相同的內容,可以向上抽取出一個類,這便形成了繼承關係
繼承得好處:
簡化了人們對事物的認識和描述,能清晰體現相關類間的層次結構關係;
能清晰體現相關類間的層次結構關係;繼承提供了軟件複用功能。這種做法能減小代碼和數據的冗餘度,大大增加程序的重用
性;提供多重繼承機制;
大大增加了程序的易維護性。
3、爲什麼用封裝
簡化代碼,方便複用,在實現一個功能的時候只需要關注結果,而不需要關注裏面做了什麼(隱藏信息,實現細節 )。
4、講講protect在java中的作用,什麼時候用它
protected修飾的變量或方法只能被當前類,同包類或者子孫類繼承或使用
一般情況下爲了實現純粹的封裝用的就是private,而使用protected可以封裝也可以繼承
當一些類,需要繼承,但是不想公開的時候可以用protect
5、串行、並行和併發
順序執行:你吃飯吃到一半,電話來了,你一直到吃完了以後纔去接,這就說明你不支持併發也不支持並行。
併發:你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支持併發。
並行:你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支持並行。
併發,指的是多個事情,在同一時間段內同時發生了。
並行,指的是多個事情,在同一時間點上同時發生了。
6、設計模式(單例)
單例:就是整個程序有且僅有一個實例。該類負責創建自己的對象,同時確保只有一個對象被創建。
懶漢模式,餓漢模式,雙重鎖機制,單例模式一般用的比較多,雙重鎖的話是處理多線程任務時,使用的一種機制。
懶漢模式:線程不安全,延遲初始化
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
餓漢模式:線程安全,比較常用,但容易產生垃圾,因爲一開始就初始化
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
雙重鎖機制:線程安全,延遲初始化。這種方式採用雙鎖機制,安全且在多線程情況下能保持高性能。
(注意volatile關鍵字)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
雙重檢查模式,進行了兩次的判斷,第一次是爲了避免不要的實例,第二次是爲了進行同步,避免多線程問題。由於singleton=new Singleton()
對象的創建在JVM中可能會進行重排序,在多線程訪問下存在風險,使用volatile
修飾signleton
實例變量有效,解決該問題
靜態內部類單例模式:
public class Singleton {
private Singleton(){
}
public static Singleton getInstance(){
return Inner.instance;
}
private static class Inner {
private static final Singleton instance = new Singleton();
}
}
只有第一次調用getInstance方法時,虛擬機才加載 Inner 並初始化instance ,只有一個線程可以獲得對象的初始化鎖,其他線程無法進行初始化,保證對象的唯一性。目前此方式是所有單例模式中最推薦的模式,但具體還是根據項目選擇。
枚舉(擴展):默認枚舉實例的創建是線程安全的,並且在任何情況下都是單例。
public enum Singleton {
INSTANCE
//doSomething 該實例支持的行爲
//可以省略此方法,通過Singleton.INSTANCE進行操作
public static Singleton getInstance() {
return Singleton.INSTANCE;
}
}
- 枚舉類隱藏了私有的構造器。
- 枚舉類的域 是相應類型的一個實例對象
- 枚舉的單例生產中使用較少,主要是太簡單以致可讀性差
6、設計模式(裝飾者設計模式(動態代理))
7、[a,b,c]、[a,b]、[a]三個索引哪一個搜的快,爲什麼
8、講講hashMap
hashMap鍵唯一,值可以不唯一。鍵是set集合,set集合保證鍵唯一的方法是,如果存的鍵是空,則默認爲0,否則進行hash值比較,如果hash值相同,則在在鍵後跟鏈表(處理hash衝突),當達到8時鏈表轉換成紅黑樹(jdk1.8之後)。
//判斷鍵值是否爲空,是則默認爲0
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
9、講講紅黑樹
10、講講GC
11、servlet生命週期
首先加載servlet的class,實例化servlet,然後初始化servlet調用init()的方法,接着調用服務的service的方法處理doGet和doPost方法,最後是我的還有容器關閉時候調用destroy 銷燬方法。
12、jsp和servlet的區別
jsp本質就是servlet,Jsp是Servlet的一種簡化,使用Jsp只需要完成程序員需要輸出到客戶端的內容,Jsp中的Java腳本如何鑲嵌到一個類中,由Jsp容器完成。
但jsp內有內置對象,servlet沒有,
jsp更擅長表現於頁面顯示,servlet更擅長於邏輯控制.
13、講講對事物的理解
14、講講ThreadLocal
15、StringBuilder、StringBuffer、String的區別
16、http和tcp的區別
17、post請求,和get請求的區別
技術篇
1、springboot定時器的配置
1、在啓動類中加入定時器的註解@EnableScheduling來註冊定時任務
2、在定時任務的方法上加上@Scheduled(cron = "0/30 * * * * ?") 並在裏面寫cron表達式
2、springboot定時器的配置多線程任務
配置一個配置類ScheduleConfig實現SchedulingConfigurer接口,並重寫裏面的方法,設定定時任務池,來實現多線程的計時任務
下面這篇博文寫的很好,可以參考
3、spingboot 定時器搭建集羣的話怎麼設置 (百度面試的)
4、springcloud運行過程中如果一臺服務處故障了,這時候怎麼處理
通常會搭建服務集羣,如果一臺服務宕機壞掉了,會Erake註冊中心映射到另一臺服務上。
5、springcloud的優點
6、springcloud的缺點
維護起來難(面試的馬上就會問,怎麼難了。。。。舉個例子,我舉你個鬼啊)
7、講講倒排索引
8、有三個索引【a,b,c】【a,b】【a】哪一個查的快,爲什麼
9、redis的五中數據類型,其中list裏面一條數據中間出錯了,能不能修改,能的話,怎麼修改,不能的話爲什麼
10、講講緩存穿透,緩存擊穿,緩存雪崩
緩存穿透:緩存中和數據庫中都沒有數據,但是用戶不停的連續發生這樣的請求,這時的用戶很可能是攻擊者,攻擊會導致數
據庫壓力過大
解決方案:將搜索信息和ip作爲key,搜索次數作爲value存進redis,設置緩存有效時間,一定時間內訪問超過一定次數的話進行攔截。
緩存擊穿: 緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期),這時由於併發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引起數據庫壓力瞬間增大,造成過大壓力
解決方案:設置redis永久有效;設置互斥鎖,當redis獲取爲空時,先獲取鎖,去數據庫中取數據,並更新redis,如果更新成功則釋放鎖;而如果拿不到鎖,證明服務正在想數據庫中獲取數據,此時線程休眠一定時間,知道拿到鎖。
緩存雪崩:緩存雪崩是指緩存中數據大批量到過期時間,而查詢數據量巨大,引起數據庫壓力過大甚至down機。和緩存擊穿不同的是, 緩存擊穿指併發查同一條數據,緩存雪崩是不同數據都過期了,很多數據都查不到從而查數據庫。
解決方案:
- 緩存數據的過期時間設置隨機,防止同一時間大量數據過期現象發生。
- 如果緩存數據庫是分佈式部署,將熱點數據均勻分佈在不同的緩存數據庫中。
- 設置熱點數據永遠不過期
11、rabbitMQ 發送消息的時候,如果消息一斤發送出去,這個時候系統出了故障,rabbitmq返回一個錯誤,又重新發送了,用戶收到了兩份內容,請問如何避免
處理這樣的問題儘量避開MQ的處理,因爲MQ處理的話會,降低消息的吞吐量。儘量在應用層設置
收消息方,收到是1,沒收到是0,還需要處理一下異常讓他不進行二次發送。
12、rabbit發送兩條消息,怎樣保證發送順序
在 MQ 層面支持消息的順序處理開銷太大,爲了極少量的需求,增加整體上的複雜度得不償失。所以,還是在應用層面處理比較好,或者業務邏輯進行處理。
應用層處理方法:
1:“同步執行”:當一個消息執行完之後,再發布下一個消息。
2、消息實體中增加:版本號 & 狀態機 & msgid & parent_msgid,通過 parent_msgid 判斷消息的順序(需要全局存儲,記錄消息的執行狀態)。
處理方式
13、講講集羣
14、ES怎麼存數據
使用ES,需要先創建相關的實體類,實體類上需要有相應的註解標明映射和類型
@Document(indexName = "skuinfo", type = "docs")
同時各個字段也要有響應註解說明是否創建索引,是否分詞,採用什麼分詞器等等
存儲數據時,需要先根據實體類創建相關索引和映射
//創建索引
elasticsearchTemplate.createIndex(SkuInfo.class);
//創建映射
elasticsearchTemplate.putMapping(SkuInfo.class);
在創建操作es的dao類,需要繼承 ElasticsearchRepository並規定泛型
public interface SkuInfoDao extends ElasticsearchRepository<SkuInfo,Long> {
}
然後直接利用裏面封裝的方法存數據
業務篇
1、講講購物車實現原理,如果購物車裏面有8件商品,提交其中兩件,問怎麼操作
2、怎樣實現秒殺,
編碼篇
1、一個數組Integer array = {2,5,1,8080,3306,9200,3,5,5,2},計算裏面出現最多的數字,如果出現相同次數的數字,返回最大的數字的次數,如上面數組中5出現3次。時間複雜度要儘可能的低,越低,分熟越高。
這裏可以用HashMap存儲相關的值,達到一次遍歷即得出結果,相關代碼自己想。
2、一個student表,有No,name,class,score共計四個字段
問1:用一條sql語句得到及格人數大於30的班級
問2:用一條sql得到每個班及格人數和不及格人數