高級Java面試總結3

1,java堆,分新生代老年代,新生代有Eden,from surviver,to surviver三個空間,堆被全部線程共。eden內存不足時,發生一次minor GC,會把from survivor和eden的對象複製到to survivor,此次的to survivor就變成了下次的from survivor,通過屢次minor GC,默認15次,達到次數的對象會從survivor進行老年代。1次new若是新生代裝不下,則直接進入老年代。前端

2,HashMap和HashTable是使用數組+鏈表結構實現,根據Hash和table長度計算數組的下標index作操做,hashMap默認數組長度爲16,hashMap對null值的key都放在table[0]的位置,table[index]造成1個鏈表,固然在新版jdk中鏈表節點數>8會變成紅黑樹結構。hashMap達到最大數量會擴容,擴容table長度變爲2倍,每一個元素(table中)但從新計算index放到新的table中。java

3,堆的年輕代和老年代。mysql

堆的年輕代大則老年代小,GC少,可是每次時間會比較長。年輕代小則老年代大,會縮短每次GC的時間,可是次數頻繁。可讓老年代儘可能緩存經常使用對象,JVM默認年輕代和老年代的大小比例爲1:2,。觀察峯值老年代內存,不影響full GC,加大老年代可調1:1,可是要給老年代預留三分之一的空間。減小使用全局變量和大對象 ,調整新生代,老年代到最合適。react

4,字節流不會用到內存緩衝區,文件自己直接操做。字符流操做使用內存緩存區,用緩存存操做文件。字符流在輸出前將全部內容暫時保存到內存中,即緩存區暫時存儲,若是想不關閉也將字符流輸出則可使用flush方法強制刷出。字節字符轉化可能存在系統編碼lang,要制定編碼。getbyte字節流使用更加普遍。nginx

5,中文佔用2個字節,read()函數讀1個字節把A會讀入的緣由。ASCII碼是8位,A在ASCII碼中有對應碼,A只要8位就能表示,可是unicode是支持ASCII碼的,在unicode中表示A是使用低8位的ASCII碼,補上高8位的0,read()1分字節就已經讀入A的ASCII碼,打印時會給其高8位補上0,因此顯示正常A。web

6,喚醒一個阻塞的線程ajax

如由於Sleep,wait,join等阻塞,可使用interrupted exception異常喚醒。redis

7,內存溢出可能緣由和解決。算法

緣由多是A,數據加載過多,如1次從數據庫中取出過多數據   B,集合類中有對對象的引用,用完後沒有清空或者集合對象未置空致使引用存在等,是的JVM沒法回收  C,死循環,過多重複對象 D,第三方軟件的bug       E,啓動參數內存值設定的太小。spring

例如方法:修改JVM啓動參數,加內存(-Xms,-Xmx);錯誤日誌,是否還有其餘錯誤;代碼走查

8,redis使用單線程模型,數據順序提交,redis支持主從模式,mencache只支持一致性hash作分佈式;redis支持數據落地,rdb定時快照和aof實時記錄操做命令的日誌備份,memcache不支持;redis數據類型豐富,有string,hash,set,list, sort set,而memcache只支持簡單數據類型;memcache使用cas樂觀鎖作一致性。

jedis操做Hash:hmset, hmget, hdel, hkeys

jedis操做List: lpush,lrange按照範圍取出,rpush, del, sort等keyjedis操做Set:sadd,srem移除noname,smembers, sismember, scard等。

使用場景例如

Hash:存儲讀取更新用戶多個屬性

List:微博TimeLine,消息列表

Set:共同好友,二度好友,用惟一性能夠統計網站全部獨立IP,好友推薦根據tag求交集,大於threshold就能夠推薦。

sortset:set增長1個權重score參數

其餘場景:A訂閱發佈系統,redis對某個key消息發佈及訂閱,當1個key消息發佈後,全部訂閱它的客戶端都會收到相應消息,例如實時消息系統,即時聊天,羣聊等。

事務-經常使用EX,EC提交執行的命令,在server不出問題,能夠保證一連串的命令是順序執行額;提供1個watch功能,對1個key做watch,而後再執行transation。

 

 

9,Class.forName()將類加載到JVM,還會對類解釋,執行static塊,而ClassLoader也加載到JVM,可是不會執行static塊,而且只有調用了new Instance方法纔會調用構造函數。

10,java反射機制。

能夠在運行時判斷一個對象所屬的類,構造一個類的對象,判斷類具備的成員變量和方法,調用1個對象的方法。4個關鍵的類:Class,Constructor,Field,Method。    getConstructor得到構造函數/getDeclardConstructor; getField/getFields/getDeclardFields得到類所生命的全部字段;getMethod/getMethods/getDeclardMethod得到類聲明的全部方法,正常方法是一個類建立對象,而反射是1個對象找到1個類。

11,Object類中的方法:clone(),可是使用該方法必須實現Java.lang.Cloneable接口,equal()方法判斷引用是否一致,指向同一對象,即相等於==,只有覆寫了equals()方法以後,才能夠說不一樣。hashcode(),對象的地址, toString(), finalize()。

12,序列化和反序列化

序列化和反序列化即對象和字節序列間的轉化,進程間傳送文本圖片音頻等以二進制傳送。JDK中ObjectOuputStream和ObjectInputStream爲輸出輸入流,只有實現SeriaLizable/Externalizable接口的類才能被序列化。如Person對象傳遞給內存流使用DataConstractJsonSeralizer, MemoryStream stream = new MemoryStream(); DataConstractJsonSeralizer SER = new DataConstractJsonSeralizer(typeof(person));  ser.writeObjectStream(stream, person);顯示json輸出,StramReader sr = new StreamReader(stream1); sr.ReadToEnd()。

13,講講分佈式惟一ID。

肯定ID存儲用64位,1個64位二進制1是這樣的00000000.....1100......0101,切割64位,某段二進制表示成1個約束條件,前41位爲毫秒時間,後緊接9位爲IP,IP以後爲自增的二進制,記錄當前面位數相同狀況下是第幾個id,如如今有10臺機器,這個id生成器生成id極限是同臺機器1ms內生成2的14次方個ID。

分佈式惟一ID = 時間戳 << 41位, int類型服務器編號 << 10,序列自增sequence。每一個時間戳內只能生成固定數量如(10萬)個自增號,達到最大值則同步等待下個時間戳,自增從0開始。將毫秒數放在最高位,保證生成的ID是趨勢遞增的,每一個業務線、每一個機房、每一個機器生成的ID都是不一樣的。如39bit毫秒數|4bit業務線|2bit機房|預留|7bit序列號。高位取2016年1月1日1到如今的毫秒數,系統運行10年,至少須要10年x365天x24小時x3600秒x1000毫秒=320x10~9,差很少39bit給毫秒數,每秒單機高峯併發小於100,差很少7bit給每毫秒的自增號,5年內機房小於100臺機器,預留2bit給機房,每一個機房小於100臺機器,預留7bit給每一個機房,業務線小於10個,預留4bit給業務線標識。

64bit分佈式ID(42bit毫秒+5bit機器ID+12位自增)等

生成分佈式ID的方式:A,2個自增表,步長相互隔開   B,時間的毫秒或者納秒  C,UUID         D,64位約束條件(如上)

14,NIO和IO的區別

第一點,NIO少了1次從內核空間到用戶空間的拷貝。

ByteBuffer.allocateDirect()分配的內存使用的是本機內存而不是Java堆上的內存,和網絡或者磁盤交互都在操做系統的內核空間中發生。allocateDirect()的區別在於這塊內存不禁java堆管理, 但仍然在同一用戶進程內。

第二點,NIO以塊處理數據,IO以流處理數據

第三點,非阻塞,NIO1個線程能夠管理多個輸入輸出通道

15,內存泄漏

未對做廢數據內存單元置爲null,儘早釋放無用對象的引用,使用臨時變量時,讓引用變量在推出活動域後自動設置爲null,暗示垃圾收集器收集;程序避免用String拼接,用StringBuffer,由於每一個String會佔用內存一塊區域;儘可能少用靜態變量(全局不會回收);不要集中建立對象尤爲大對象,可使用流操做;儘可能使用對象池,再也不循環中建立對象,優化配置;建立對象到單例getInstance中,對象沒法回收被單例引用;服務器session時間設置過長也會引發內存泄漏。

16,對象克隆和實現方式

克隆的對象可能包含一些已經修改過的屬性,而new1個對象屬性都仍是初始化時候的值,被複制克隆的類要實現Clonable接口,覆蓋clone()方法,訪問修飾符爲public,方法中調用super.clone()獲得所須要的複製方法,類中的屬性類也須要實現Clonable接口,覆寫clone()方法,並在super中也調用子屬性類的clone()複製,才能夠實現深拷貝。

或者寫到流中序列化的方式來實現,沒必要考慮引用類型中還包含引用類型,直接用序列化來實現對象的深複製拷貝,即將對象寫到流,再從流中讀出來,須要實現seriazation接口。

17,redis內存數據上升到必定大小會執行數據淘汰策略,redis提供了6種數據淘汰策略。

LRU:從已設置過時時間的數據集合中挑選最近最少使用的數據淘汰

random:從已設置過時時間的數據中挑選任意數據淘汰

ttl:從已設置過時時間的數據集合中挑選將要過時的數據淘汰。

notenvision:禁止驅逐數據

如mysql中有2千萬數據,redis只存儲20萬的熱門數據。LRU或者TTL都知足熱點數據讀取較多,不太可能超時特色。

redis特色:速度塊,O(1),豐富的數據類型,支持事物原子性,可用於緩存,比memecache速度塊,能夠持久化數據。

常見問題和解決:Master最好不作持久化如RDB快照和AOF日誌文件;若是數據比較重要,某分slave開啓AOF備份數據,策略爲每秒1次,爲了主從複製速度及穩定,MS主從在同一局域網內;主從複製不要用圖狀結構,用單向鏈表更爲穩定 M-S-S-S-S。。。。;redis過時採用懶漢+按期,懶漢即get/set時候檢查key是否過時,過時則刪除key,按期遍歷每一個DB,檢查制定個數個key;結合服務器性能調節併發狀況。

過時淘汰,數據寫入redis會附帶1個有效時間,這個有效時間內該數據被認爲是正確的並不關心真實狀況,例如對支付等業務採用版本號實現,redis中每一份數據都維持1個版本號,DB中也維持1份,只有當redis的與DB中的版本一致時,纔會認爲redis爲有效的,不過仍然每次都要訪問DB,只須要查詢version版本字段便可。

18,異步化,生產接口每秒鐘10萬併發,消費者用異步慢慢消費。緩存模式空間換時間,把1兩億的數據名單打到緩存。服務降級,把不重要的任務放棄;靜態資源離線包下載機制,在wify下會主動提早把靜態下載前端層保護可請將用戶請求延長,點擊後主動給它隨機等待2s的時間/2分鐘以內不能請求;後端作部分接口的開關,設置超短耗時時間,原來只用5ms的只給20ms。

系統一段時間內會自動重試,重試屢次後就認爲是失敗了,檢查支付接口返回該訂單的錢,支付操做若是回覆錯誤則回滾扣庫存的事務,沒返回則會記錄進行中pendding狀態,結束整個過程,等通知失敗/成功,AB系統之間會出現死循環補償,如B退單不成功,通常就是記錄錯誤日誌了。超時每隔一段時間去定時回調服務定時回滾,必定次數仍是超時則提示用戶聯繫客服,訂單庫存能夠不會滾,記錄狀態,若是一直調用支付不成功,則讓用戶本身去處理聯繫客服,能夠不回滾用戶的數據,金額扣了纔算真正完成,是一種簡單粗暴的作法。

公共配置抽象成存儲到zookeeper配置中心或者redis等,DB也存儲一份,各應用監聽ZK的配置變化,能夠建一個配置web管理頁面。

19,dubbo用ProxyFactoty代理工廠將HelloServiceImpl封裝成1個Inoke執行,即ProxyFactory.getInvoke(ref, (Class)接口,註冊URL,解碼參數),並將Invoke導出成1個Exporter,包括去註冊中心ZK註冊服務。Invoke有本地執行的Invoke,遠程通訊執行的Invoke。

20,每次扣減庫存時加上1個請求流水編號,上層請求扣減庫存沒拿到結果的話,從新查詢1次作重試操做,量不大都是加鎖處理。減小鎖的時間,犧牲冪等性,扣減爲DB下地操做,查詢扣減和設置合成1步,中間沒有網絡請求。利用緩存,經過寫log記錄操做,異步合併日誌及更新,重啓時cache失效,讀log恢復,避免重複提交,寫操做不建議重試快速失敗。多個商品同時增減庫存,可以使用訂單號作冪等處理,應用層對單個商品減庫存,操做排隊,商品消息ID路由在1個應用server處理,讀本地緩存,失效再redis,DB採用樂觀鎖,組提交,1次減庫存多個訂單的購買量。可將同一個key下庫存m分爲n組k1......kn,每組數爲m/n,扣減依次在各組扣減,減小併發衝突。隊列裝滿後關閉隊列進入,而後用戶輪訓本身是否搶到了異步ajax,用戶資源隊列固定長度。2個隊列,1個銷售的資源隊列放入redis,有另外1個隊列用來裝搶購的會員的uid。

紅包狀態正常,併成功將狀態改成「已領取」,且消息發送成功,用戶端開始消費該消息,若是消費失敗/超時,用MQ作重試作冪等,直到成功,每條消息有惟一編號且保證消息處理成功與去重表的日誌同時出現。

熱點將hot data拆分,分在不一樣庫和不一樣表,分散熱點Data,減輕DB併發更新熱點帶來RT升高和應用鏈接超時。SQL在mysql層加以限制,SQL超時/thradrunning到1定值則拒絕SQL執行,必定時間異步將結果寫入DB,nginx對IP作限制,可能誤殺。

21,SpringAOP,XML配置<aop:config>,切面<aop:aspect>切點<aop:pointcut>,鏈接切點和通知方法<aop:before>和<aop:after>等,註解能夠直接使用@before執行方法@after ,@before(「pointcut()」) ,@after("pointcut"), @Aroud("excutete()),@AfteReturning,@AfterThrowing,可做日誌事務,權限等待,AOP即經過把具體的類建立對應的 代理類,從代理類來對具體進行操做。                      

目標實現了接口,默認採用JDK實現AOP,也能夠強制使用CGlib來實現AOP,目標沒有實現接口的話,則必須採用CGlib,Spring自動在JDK和CGlib切換。若是要求spring強制使用CGlib實現AOP,則能夠配置,添加Cglib庫。。。jar, Spring配置文件中加入<aop:aspecj-autoproxy proxy-target-Class=true>                                                                                                                                                                                   

22,MyISM採用表級鎖,對Myism表讀不會阻塞讀,會阻塞同表寫,對Myism寫則會阻塞讀和寫,即一個線程得到1個表的寫鎖後,只有持有鎖的線程能夠對錶更新操做,其餘線程的讀和寫都會等待。

InnoDB,採用行級鎖,支持事務,例如只對a列加索引,若是update ...where a=1 and b=2其實也會鎖整個表, select 使用共享鎖,update insert delete採用排它鎖,commit會把鎖取消,固然select by id for update也能夠制定排它鎖。

23,實時隊列採用雙隊列模式,生產者將行爲記錄寫入Queue1,worker服務從Queue1消費新鮮數據,若是異常則寫入Queue2(主要保存異常數據),RetryWorker會監聽Queue2,消費異常數據,若是還未處理成功按照必定的策略等待或者將異常數據再寫入Queue2,若是數據發生積壓能夠調整worker的消費遊標,從最新數據從新開始消費,保證了最新data獲得處理,中間未處理的一段則能夠啓動backupWorker指定起止遊標在消費完指定區間的數據後,backupWorker會自動中止。

DB降級開關後,可直接寫入redis(storm),同時將數據寫入一份到Retry隊列,在開啓DB降級開關後消費Retry隊列中的數據,從而把數據寫入到mysql中,達到最終一致性。MYSQL切分爲分片爲2的N次方,例如原來分爲兩個庫d0和d1均放在s0服務器上,s0同時有備機s1,擴容只要幾步驟:確保s0到s1服務器同步順利,沒有明顯延遲;s0暫時關閉讀寫權限;確保s1已經徹底同步到s0更新;s1開放讀寫權限;d1的dns由s0切換到s1;s0開放讀寫權限。

24,DB的特性和隔離級別

4大特性:原子性,一致性,分離性,持久性

隔離級別:

讀提交:寫事務禁止讀

讀未提交:寫事務容許讀

可重複讀:寫事務禁止讀事務,讀禁止寫

序列化:所有禁止

詳細說明:讀提交1個事務開始寫則所有禁止其餘事務訪問該行。讀未提交1個事務開始寫則不容許其餘事務同時寫,但能夠讀。可重複讀 讀事務會禁止寫事務,寫事物則禁止其餘任何事務。序列化性能最低,所有禁止,串行執行。 MYSQL默認的是可重複讀。

25,帖子服務、元數據服務、帖子搜索服務,提供索引數據存儲,tid和uid查詢直接從帖子服務從元數據返回,其餘檢索查詢有帖子搜索服務從索引數據檢索並返回,帖子服務增刪改查用MQ同步到帖子搜索服務,搜索服務修改索引的數據(索引樹,倒排表),索引表t_mapping(tid,uid)。

300億數據在全量索引庫中,數百萬一天內修改過的數據在一天庫中,50萬小時內修改過的數據在小時庫中,在update請求時,只會操做最低級別的索引例如小時庫。小時庫,1小時合併一次,合併到天庫,天庫一天合併1次,合併到全量庫中。

26,講一下NIO和網絡傳輸

NIO Reactor反應器模式,例如汽車是乘客訪問的實體reactor,乘客上車後到售票員處Acceptor登記,以後乘客即可休息睡覺了,到達乘客目的地後,售票員Aceptor將其喚醒便可。持久TCP長連接每一個client和server之間有存在一個持久鏈接,當CCU(用戶併發數量)上升,阻塞server沒法爲每一個鏈接運行1個線程,本身開發1個二進制協議,將message壓縮至3-6倍,傳輸雙向且消息頻率高,假設server連接了2000個client,每一個client平均每分鐘傳輸1-10個message,1個messaged的大小爲幾百字節/幾千字節,而server也要向client廣播其餘玩家的當前信息,須要高速處理消息的能力。Buffer,網絡字節存放傳輸的地方,從channel中讀寫,從buffer做爲中間存儲格式,channel是網絡鏈接與buffer間數據通道,像以前的socket的stream。

27,緩存擊透

預加載;

加載DB時同步,其餘則等待;

DB端作SQL合併,Queue合併排隊處理;

部分緩存設置爲永不過時;

先清除緩存,讀取數據時候則等待500ms,500ms緩存應該已經加載完成;

採用雙key緩存,A1爲原始緩存,A2爲拷貝緩存;

若是DB爲空null則g給redis設置1個NFC空nei容。

28,Dubbo源碼使用了哪些設計模式

A,工廠模式,ExtenstionLoader.getExtenstionLoader(Protocol.class).getAdaptiveExtenstion()

B,裝飾器模式+責任鏈,以provider的調用鏈爲例,具體調用鏈代碼是在protocolFilterWrapper的buildInvokeChain完成的,將註解中含有group=provider的Filter實現,調用順序爲EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter -> ExceptionFilter -> TimeoutFilter -> MonitorFilter -> TraceFilter。裝飾器模式和責任鏈混合使用,Echo是回聲測試請求,ClassLoaderFilter則只是在其主功能上添加了功能。

C,觀察者模式,provider啓動時須要與註冊中心交互,先註冊本身的服務,再訂閱本身的服務,訂閱時採用了觀察者模式,註冊中心每5s定時檢查是否有服務更新,有更新則向服務提供者發送1個notify消息後便可運行NotifyListener的notity方法,執行監聽器方法。

D,動態代理模式。  擴展JDK的ExtensionLoaderdeAdaptive實現,根據調用階段動態參數決定調用哪一個類,生成代理類的代碼是ExtensionLoader的createAdaptiveExtenstionClassLoader方法。

29,平衡二叉樹,左右高度之差不超過1,Add/delete可能形成高度>1,此時要旋轉,維持平衡狀態,避免二叉樹退化爲鏈表,讓Add/Delete時間複雜度但控制在O(log2N),旋轉算法2個方法,1是求樹的高度,2是求2個高度最大值,1個空樹高度爲-1,只有1個根節點的樹的高度爲0,之後每一層+1,平衡樹任意節點最多有2個兒子,所以高度不平衡時,此節點的2棵子樹高度差爲2。例如單旋轉,雙旋轉,插入等。

紅黑樹放棄徹底平衡,追求大體平衡,保證每次插入最多要3次旋轉就能平衡。

30,多線程同步鎖

A,RentrantLock,可重入的互斥鎖,可中斷可限時,公平鎖,必須在finally釋放鎖,而synchronize由JVM釋放。可重入可是要重複退出,普通的lock()不能響應中斷,lock.lockInterruptbly()可響應中斷,能夠限時tryLock(),超時返回false,不會永久等待構成死鎖。

B,Confition條件變量,signal喚醒其中1個在等待的線程,signalall喚醒全部在等待的線程await()等待並釋放鎖,與lock結合使用。

C,semaphore信號量,多個線程比(額度=10)進入臨界區,其餘則阻塞在臨界區外。

D,ReadWriteLock,讀讀不互斥,讀寫互斥,寫寫互斥。

E,CountDownLantch倒數計時器,countdown()和await()

F,CyCliBarrier

G,LockSupport,方法park和unpark

31,棧溢出的緣由

是否遞歸的調用;大量循環;全局變量是否過多;數組,List,Map數據是否過大;用DDMS工具檢查地方。

內存溢出的緣由

過多使用了static;static最好只用int和string等基本類型;大量的遞歸或者死循環;大數據項的查詢,如返回表的全部記錄,應該採用分頁查詢。檢查是否有數組、List、map中存放的是對象的引用而不是對象,這些引用會讓對應對象不能被釋放。

棧過大會致使內存佔用過多,頻繁頁交換阻礙效率。

32,說一下http/2

Http/2採用二進制格式而不是文本

Http/2是徹底多路複用的,而非有序並阻塞的。

Http/2使用報頭壓縮

Http/2讓服務器能夠將響應主動推送到客戶端緩存中。

33,說一下內存泄露

A,HashMap,vector等容易(靜態集合類), 和應用程序生命週期同樣,所引用的全部對象Object也不能釋放。

B,當集合類裏面的對象屬性被修改後,再調用remove()不起做用,hashcode值發生了改變

C,其對象add監聽器,可是每每釋放對象時忘記去刪除這些監聽器

D,各類鏈接記得關閉

E,內部類的引用

F,調用其餘模塊,對象做用參數

G,單例模式,持有外部對象引用沒法收回。

內存泄露例子

Vector<String> A = new Vector<String>();

for(int i = 0; i < 100; i++){

Object o = new Object ();

A.add(o);

o = null;

}

 ........

內存溢出的例子

StringBuffer b = new StringBuffer ();

for(int i =0; i < 100; i++){

for(int j =0; i < 100; j++){

b.append(*);

}

}

34,SpirngMVC的生命週期 和 SpringBean的生命週期

SpirngMVC的生命週期 :

A,DispatcherSerlvet(前端控制器)

B,-》 HandlerMapping(處理器映射器),根據xml註解查找對應的Hander -》 返回Handler

C,-》處理器適配器去執行Handler

D,-》Handler執行完成後給處理器適配器返回ModelAndView

E,-》前端控制器請求視圖解析器去執行視圖解析,根據邏輯視圖名解析成真正的視圖JSP,向前端控制器返回view

F,-》前端控制器進行視圖渲染,將模型數據放到request-》返回給用戶

SpringBean的生命週期:

Instance實例化-》設置屬性值-》調用BeanNameAware的setBeanName方法-》調用BeanPostProsessor的預初始化方法-》調用InitializationBean的afterPropertiesSet()的方法-》調用定製的初始化方法callCustom的init-method-》調用BeanPostProsessor的後初始化方法-》Bean可使用了 -》 容器關閉-》 調用DisposableBean的destroy方法-》調用定製的銷燬方法CallCustom的destroy-method。

35,AQS,抽象隊列同步器

AQS定義2種資源共享方式:獨佔與share共享

獨佔:只能有1個線程運行

share共享:多個線程能夠同p執行如samphore/countdownlanch

AQS負責獲取共享state的入隊和/喚醒出隊等,AQS在頂層已經實現好了,AQS有幾種方法:acquire()是獨佔模式下線程共享資源的頂層入口,如獲取到資源,線程直接返回,不然進入等待隊列,直到獲取到資源爲止。tryAcquire()將線程加入等待隊列的尾部,並標誌爲獨佔。acquireQueued()使線程在等待隊列中獲取資源,一直到獲取資源後不返回,若是過程被中斷也返回true,不然false。

線程在等待過程當中被中斷是不響應的,獲取資源才補上中斷。將線程添加到隊列尾部用了CAS自旋(死循環直到成功),相似於AutomicInteger的CAS自旋volatile變量。

start->tryAcquire -> 入隊 -> 找安全點 -> park等待狀態 -> 當前節點成對頭 -> End

36,單例模式的7種寫法

懶漢2種,枚舉,餓漢2種,靜態內部類,雙重校驗鎖(推薦)。

37,lucence倒排索引

三個文件:字典文件,頻率文件,位置文件。詞典文件不只保存有每一個關鍵詞,還保留了指向頻率文件和位置文件的指針,經過指針能夠找到該關鍵字的頻率信息和位置信息。

field的概念,用於表達信息所在位置(如標題中,文章中,url中),在建索引中,該field信息也記錄在詞典文件中,每一個關鍵詞都有一個field信息(由於每一個關鍵字必定屬於一個或多個field)。

關鍵字是按字符順序排列的(lucene沒有使用B樹結構),所以lucene能夠用二元搜索算法快速定位關鍵詞。

假設要查詢單詞 「live」,lucene先對詞典二元查找、找到該詞,經過指向頻率文件的指針讀出全部文章號,而後返回結果。詞典一般很是小,於是,整個過程的時間是毫秒級的。   

對詞典文件中的關鍵詞進行了壓縮,關鍵詞壓縮爲<前綴長度,後綴>,例如:當前詞爲「阿拉伯語」,上一個詞爲「阿拉伯」,那麼「阿拉伯語」壓縮爲<3,語>。對數字的壓縮,數字只保存與上一個值的差值。

38,ZooKeeper分佈式高可用

ZooKeeper 運行期間,集羣中至少有過半的機器保存了最新數據。集羣超過半數的機器可以正常工做,集羣就可以對外提供服務。

zookeeper能夠選出N臺機器做主機,它能夠實現M:N的備份;keepalive只能選出1臺機器做主機,因此keepalive只能實現M:1的備份。

一般有如下兩種部署方案:雙機房部署(一個穩定性更好、設備更可靠的機房,這個機房就是主要機房,而另一個機房則更加廉價一些,例如,對於一個由 7 臺機器組成的 ZooKeeper 集羣,一般在主要機房中部署 4 臺機器,剩下的 3 臺機器部署到另一個機房中);三機房部署(不管哪一個機房發生了故障,剩下兩個機房的機器數量都超過半數。在三個機房中都部署若干個機器來組成一個 ZooKeeper 集羣。假設機器總數爲 N,各機房機器數:N1 = (N-1)/2 ,N2=1~(N-N1)/2 ,N3 = N - N1 - N2 )。

水平擴容就是向集羣中添加更多機器,Zookeeper2種方式(不完美),一種是集羣總體重啓,另一種是逐臺進行服務器的重啓。

相關文章
相關標籤/搜索