一、 對於查詢頻率高的字段建立索引; 二、 對排序、分組、聯合查詢頻率高的字段建立索引; 三、 索引的數目不宜太多 緣由:a、每建立一個索引都會佔用相應的物理控件; b、過多的索引會致使insert、update、delete語句的執行效率下降; 四、若在實際中,須要將多個列設置索引時,能夠採用多列索引 如:某個表(假設表名爲Student),存在多個字段(StudentNo, StudentName, Sex, Address, Phone, BirthDate),其中須要對StudentNo,StudentName字段進行查詢,對Sex字段進行分組,對BirthDate字段進行排序,此時能夠建立多列索引 index index_name (StudentNo, StudentName, Sex, BirthDate); #index_name爲索引名 在上面的語句中只建立了一個索引,可是對4個字段都賦予了索引的功能。 建立多列索引,須要遵循BTree類型, 即第一列使用時,才啓用索引。 在上面的建立語句中,只有mysql語句在使用到StudentNo字段時,索引纔會被啓用。 如: select * from Student where StudentNo = 1000; #使用到了StudentNo字段,索引被啓用。 能夠使用explain檢測索引是否被啓用 如:explain select * from Student where StudentNo = 1000; 五、選擇惟一性索引 惟一性索引的值是惟一的,能夠更快速的經過該索引來肯定某條記錄。例如,學生表中學號是具備惟一性的字段。爲該字段創建惟一性索引能夠很快的肯定某個學生的信息。若是使用姓名的話,可能存在同名現象,從而下降查詢速度。 六、儘可能使用數據量少的索引 若是索引的值很長,那麼查詢的速度會受到影響。例如,對一個CHAR(100)類型的字段進行全文檢索須要的時間確定要比對CHAR(10)類型的字段須要的時間要多。 七、儘可能使用前綴來索引 若是索引字段的值很長,最好使用值的前綴來索引。例如,TEXT和BLOG類型的字段,進行全文檢索會很浪費時間。若是隻檢索字段的前面的若干個字符,這樣能夠提升檢索速度。 八、刪除再也不使用或者不多使用的索引. 表中的數據被大量更新,或者數據的使用方式被改變後,原有的一些索引可能再也不須要。數據庫管理員應當按期找出這些索引,將它們刪除,從而減小索引對更新操做的影響
B+ tree樹索引, B tree, 散列
InnoDB: 事務型存儲引擎, 而且有較高的併發讀取頻率 MEMORY: 存儲引擎,存放在內存中,數據量小, 速度快 Merge: ARCHIVE: 歸檔, 有很好的壓縮機制
1. 分庫分表: 一樣量的數據平均存儲在不一樣數據庫相同表(或不一樣表)中,減輕單表壓力,若是仍是很大,就能夠每一個庫在分多張表,根據hash取值或者其餘邏輯判斷將數據存儲在哪張表中 2. 讀寫分離: 數據庫本來就有主從數據庫之分,查詢在從服務器,增刪改在主服務器, 3. 歸檔和操做表區分: 建一張歸檔表,將歷史數據放入,須要操做的表數據單獨存儲 4. 索引啊之類的建立,對於數據量很大,百萬級別以上的單表,若是增刪改操做不頻繁的話, 能夠建立bitMap索引,速度要快得多
1. 共享鎖:要等第一我的操做完,釋放鎖,才能操做 2. 更新鎖:解決死鎖,別人能夠讀,但不能操做 3. 排他鎖:讀寫都被禁用 4. 意向鎖(xlock): 對錶中部分數據加鎖,查詢時,能夠跳過 5. 計劃鎖: 操做時,別的錶鏈接不了這張表,
1. 原子性: 全部操做要麼所有成功,要麼所有失敗 2. 一致性: 例如轉帳,一個事務執行前和執行後必須一致 3. 隔離性: 防止髒讀, 重複讀問題 4. 持久性: 永久性提交數據庫
Concat: 字符串拼接, 或者 || Instr: 指定字符串位置 Length: 長度 Trim: 去空格 Lower: 小寫 Upper:大寫 Nvl: 判斷空 Replace: 替換 Substr: 截取 Floor: 向下取整 To_number: To_char: To_date: Decode: 判斷函數等等
1. 查詢謂詞沒有使用索引的主要邊界,換句話說就是select *,可能會致使不走索引 2. 單鍵值的b樹索引列上存在null值,致使COUNT(*)不能走索引。索引列存在空值 3. 索引列上有函數運算,致使不走索引 4. 隱式類型轉換致使不走索引。 5. 表的數據庫小或者須要選擇大部分數據,不走索引 6. !=或者<>(不等於),可能致使不走索引 7. 表字段的屬性致使不走索引,字符型的索引列會致使優化器認爲須要掃描索引大部分數據且聚簇因子很大,最終致使棄用索引掃描而改用全表掃描方式, 8. 使用like, in 等, 可能致使不走索引
1.如何設計能夠動態擴容縮容的分庫分表方案?? 2.用過哪些分庫表中間件, 有啥優缺點??講一下你瞭解的分庫分表中間件的底層實現原理?? 3.我如今有一個未分庫分表的系統,之後系統需分庫分表,如何設計,讓未分庫分表的系統動態切換到分庫分表的系統上?? 4.分佈式事務知道麼? 大家怎麼解決的?? TCC ?? 那若吃醋先網絡緣由,網絡連不通怎麼辦?? 5.爲何要分庫分表?? 6.分佈式尋址方式都有哪些算法?? 知道一致性hash嗎??手寫一下java實現代碼??你若userId取摸分片,那我要查一段連續時間裏的數據怎麼辦? 7.如何解決分庫分表主鍵問題??有什麼實現方案?html
1.Redis和memcheched 什麼區別??爲何單線程的redis比多線程的memched效率要高?? 2.Redis有什麼數據類型??都在哪些場景下使用?? 3.redis主從複製是怎麼實現的??Redis的集羣模式是如何實現的??redis的key是如何尋址的?? 4.使用redis如何設計分佈式鎖, 使用zk能夠麼??如何實現??這兩種那個效率更高?? 5.知道redis的持久化麼?? 都有什麼優缺點??具體底層實現呢?? 6.Redis過時策略都有哪些??LRU??寫一下java版本的代碼??前端
1.說一下dubbo的實現過程??註冊中心掛了能夠繼續通訊麼?? 2.Zk原理知道嗎?Zk均可以幹什麼??Paxos算法知道嗎??說一下原理和實現?? 3.Dubbo支持哪些序列號協議??Hessian??說一下hession的數據結構??PB知道嗎??爲啥PB效率是最高的?? 4.知道netty麼??Netty能夠幹嗎啊??NIO, BIO, AIO都是什麼啊?有什麼區別麼? 5.Dubbo複製均衡策略和高可用策略都有哪些??動態代理策略呢?? 6.爲何要進行系統拆分啊??拆分不用dubbo能夠嗎??Dubbo和thrift什麼區別?? 7.Mq相關?java
不必定相等,都不必定至關。 反過來(equals相同,hashcode相同,則類相同)可能成立 Equals用來判斷兩個對象的值是否相等, ==用來判斷兩個對象的引用地址和值是否相等
分兩種: Collection: 包含獨立元素, 能夠重複,無序的, 繼承了iterable接口,有一個iterator方法返回迭代器對象, 相關接口有list, queue, set Map: 包含鍵值對的元素,key不重複,value容許重複, 實現接口TreeMap, HashMap, LinkedhashMap, concurrentHashMap, hasTable
hashmap非線程安全的,key和value能夠接收nul值 Hashtable線程安全的,不能接受null 單線程下,hashmap比hashtable快得多 concurrentHashMap融合了hashtable和hashmap的優勢,寫能夠多線程寫,而且是線程安全的,讀線程不受限制
Hashmap: 數組方式存儲, 線程非安全,可存儲null, 無序 Treemap: 基於二叉樹實現方式, 線程非安全,不容許null, 存入元素需實現comparable接口, 自定義排序規則。
核心池大小 線程池最大線程數 保持多久時間會終止 阻塞隊列,存儲等待執行的任務 ; Java經過Executors能夠提供四種線程池
1.synchnized 是關鍵字,在方法出錯以後由java虛擬機自動解除鎖定,而 Lock屬於Api級別的鎖,它須要本身在 finally方法後面保證鎖的釋放。 2.synchnized 不能實現公平鎖,而 Lock能夠,Lock還能夠添加多個監聽條件來對鎖進行控制,能夠中斷。 3.synchronized 做用在普通方法上屬於對象鎖,做用在靜態方法,類.class 上面,屬於全局鎖。對象鎖只對同一個對象加鎖,做用對象是同一個對象。而類鎖是對類加鎖,對整個類都有效。 若是鎖住的是通常方法就是對象鎖,對象鎖只會對同一個對象起做用,若是是鎖住了static 方法則是全局鎖,會對全局對象都管用,若是想在普通方法中使用全局鎖須要鎖住class對象。
ThreadLocal 底層是存儲在 線程本地Map裏面的一個對象,它跟當前線程綁定,以 ThreadLocal 對象自己爲 key,以ThreadLocal裏面存的值爲值,目的是爲了實現線程之間的數據的隔離。 public static final ThreadLocal session = new ThreadLocal(); public static Session getCurrentSession() { Session s = (Session)session.get(); if(s == null){ s = sessionFactory.openSession(); session.set(s); } return s; }
8.Volitile的工做原理??mysql
實例化一個對象其實能夠分爲三個步驟: (1)分配內存空間。 (2)初始化對象。 (3)將內存空間的地址賦值給對應的引用。 多線程狀況下,Volitile修飾的變量會被加一個lock指令,這個指令作兩件事情, 1.在變量改變以後,會馬上從cpu高速緩存寫到內存 2.會通知其餘cpu緩存中的該變量的值設置成無效,用到該變量時會到內存中從新讀取該變量的值。 Lock指令保證了緩存一致性原理
9.Cas知道麼??如何實現的??react
CAS(Compare and Swap)即比較並替換,實現併發算法時經常使用到的一種技術, 三個參數,比較是否相等,當內存值和預期值相等時,纔會將第三個值更新,並返回true
10.請用至少四種寫法, 寫一個單例模式唄??nginx
1. 實例靜態類 2. volitile修飾,sychnized修飾 3. 枚舉使用(推薦)
1.請介紹一下jvm內存模型?? 用過什麼垃圾回收器?? 都說說吧?? 2.線上發送頻繁full gc如何處理?? cpu使用率太高怎麼辦?? 如何定位問題??如何解決??說一下解決思路和處理方法?? 3.知道字節碼麼?字節碼都有哪些?Integer x =5 , int y = 5 , 比較x == y 都須要通過哪些步驟?? 4.講講類加載機制唄??都有哪些類加載器??這寫類加載器都加載哪些文件??手寫一下類加載demo?? 5.知道osgi麼??他是如何實現的?? 6.請問你作過哪些JVM優化??使用什麼方法??達到什麼效果?? 7.Class.forName(「java.lang.String」)和String.class.getClassLoader().loadClass(「java.lang.String」)有什麼區別麼??web
1.spring都有哪些機制??AOP底層如何實現的??IOC呢?? 2.Cglib知道麼??他和jdk動態代理什麼區別??手寫一個jdk動態代理吧??ajax
1.爲何是用消息隊列??消息隊列有什麼優勢和缺點?? 2.如何保證消息隊列的高可用性??如何保證消息不被重複消費?? 3.Kafka, activemq , rabbitmq, rocketmq 都有什麼優缺點?? 4.若是讓你寫一個消息隊列, 該如何進行架構設計??說一下你的思路正則表達式
1.Es的工做過程實現是如何的?? 如何實現分佈式的?? 2.Es在數據量很大的狀況下(數十億級別)如何提升查詢效率?? 3.Es的查詢是一個怎麼的工做過程??底層lucence介紹一下??倒排索引知道麼??Es和mongdb什麼區別啊??都在什麼場景下使用啊??redis
1.如何設計一個高併發高可用系統?? 2.如何限流??工程中怎麼作的??說一下具體實現?? 3.緩存如何使用的??緩存使用不當會形成什麼後果?? 4.如何熔斷啊??熔斷框架都有哪些??具體實現原理知道嗎?? 5.如何降級??如何進行系統拆分??如何數據庫拆分??
1.說一下TCP/IP四層?? 2.http的工做流程??http1.0, http1.1 , http2.0 具體哪些區別?? 3.Tcp三次握手, 四層分手的工做流程??畫一下流程圖??爲何不是四次五次或者二次啊?? 4.畫一下https的工做原理??具體如何實現的,如何防止被抓包啊??
1.比較簡單, 我一個文件, 有45億個阿拉伯數字, 如何進行去重啊??如何找出最大的那個數啊??
1.二叉樹和紅黑數等??
請簡要描述一下J2EE應用中的class loader的層次結構? java1.7 和1.8中,hashmap的區別 mybatis一級緩存,二級緩存,緩存策略 osi七層網絡模型,五層網絡模型,每次層分別有哪些協議 死鎖產生的條件, 以及如何避免死鎖,銀行家算法,產生死鎖後如何解決 如何判斷鏈表有環 虛擬機類加載機制,雙親委派模型,以及爲何要實現雙親委派模型 虛擬機調優參數 拆箱裝箱的原理 JVM垃圾回收算法 CMS G1 hashset和hashmap的區別,haspmap的底層實現put操做,擴容機制,currenthashmap如何解決線程安全,1.7版本以及1.8版本的不一樣md5加密的原理 有多少種方法可讓線程阻塞,能說多少說多少 synchronized和reetrantlock鎖 AQS同步器框架,countdowmlatch,cyclebarrier,semaphore,讀寫鎖
B-Tree索引,myisam和innodb中索引的區別 BIO和NIO的應用場景 講講threadlocal 數據庫隔離級別,每層級別分別用什麼方法實現,三級封鎖協議,共享鎖排它鎖,mvcc多版本併發控制協議,間隙鎖 數據庫索引?B+樹?爲何要建索引?什麼樣的字段須要建索引,建索引的時候通常考慮什麼?索引會不會使插入、刪除做效率變低,怎麼解決? 數據庫表怎麼設計的?數據庫範式?設計的過程當中須要注意什麼? 共享鎖與非共享鎖、一個事務鎖住了一條數據,另外一個事務能查嗎? Spring bean的生命週期?默認建立的模式是什麼?不想單例怎麼辦?
高併發時怎麼限流 線程池的拒接任務策略 springboot的啓動流程 集羣、負載均衡、分佈式、數據一致性的區別與關係 數據庫若是讓你來垂直和水平拆分,誰先拆分,拆分的原則有哪些(單表數據量多大拆) 最後談談Redis、Kafka、 Dubbo,各自的設計原理和應用場景
6,喚醒一個阻塞的線程 如由於Sleep,wait,join等阻塞,能夠使用interrupted exception異常喚醒。
8,redis使用單線程模型,數據順序提交,redis支持主從模式,mencache只支持一致性hash作分佈式;redis支持數據落地,rdb定時快照和aof實時記錄操做命令的日誌備份,memcache不支持;redis數據類型豐富,有string,hash,set,list, sort set,而memcache只支持簡單數據類型;memcache使用cas樂觀鎖作一致性。
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種方式(不完美),一種是集羣總體重啓,另一種是逐臺進行服務器的重啓。
39,如何將數據分佈在redis第幾個庫?
答:redis 自己支持16個數據庫,經過 數據庫id 設置,默認爲0。 例如jedis客戶端設置。一:JedisPool(org.apache.commons.pool.impl.GenericObjectPool.Config poolConfig, String host, int port, int timeout, String password, int database); 第一種經過指定構造函數database字段選擇庫,不設置則默認0庫。二:jedis.select(index);調用jedis的select方法指定。
40,類加載器的雙親委派加載機制?
答:當一個類收到了類加載請求,他首先不會嘗試本身去加載這個類,而是把這個請求委派給父類去完成,每個層次類加載器都是如此,所以全部的加載請求都應該傳送到啓動類加載其中,只有當父類加載器反饋本身沒法完成這個請求的時候(在它的加載路徑下沒有找到所需加載的Class),子類加載器纔會嘗試本身去加載。
41,kafka高性能的緣由?
答:
A,Broker NIO異步消息處理,實現了IO線程與業務線程分離;
B,磁盤順序寫;
C, 零拷貝(跳過用戶緩衝區的拷貝,創建一個磁盤空間和內存的直接映射,數據再也不復制到用戶態緩衝區);
D,分區/分段(每次文件操做都是對一個小文件的操做,很是輕便,同時也增長了並行處理能力);
F,批量發送 (能夠指定緩存的消息達到某個量的時候就發出去,或者緩存了固定的時間後就發送出去,大大減小服務端的I/O次數)
E,數據壓縮
42,冪等的處理方式?
答:1、查詢與刪除操做是自然冪等
2、惟一索引,防止新增髒數據
3、token機制,防止頁面重複提交
4、悲觀鎖 for update
5、樂觀鎖(經過版本號/時間戳實現, 經過條件限制where avai_amount-#subAmount# >= 0)
6、分佈式鎖
7、狀態機冪等(若是狀態機已經處於下一個狀態,這時候來了一個上一個狀態的變動,理論上是不可以變動的,這樣的話,保證了有限狀態機的冪等。)
8、select + insert(併發不高的後臺系統,或者一些任務JOB,爲了支持冪等,支持重複執行)
43,HTTPS工做流程? a、客戶端發送本身支持的加密規則給服務器,表明告訴服務器要進行鏈接了 b、服務器從中選出一套加密算法和hash算法以及本身的身份信息(地址等)以證書的形式發送給瀏覽器,證書中包含服務器信息,加密公鑰,證書的辦法機構 c、客戶端收到網站的證書以後要作下面的事情: c一、驗證證書的合法性 c二、若是驗證經過證書,瀏覽器會生成一串隨機數做爲密鑰K,並用證書中的公鑰進行加密 c三、用約定好的hash算法計算握手消息,而後用生成的密鑰K進行加密,而後一塊兒發送給服務器 d、服務器接收到客戶端傳送來的信息,要求下面的事情: d一、用私鑰解析出密碼,用密碼解析握手消息,驗證hash值是否和瀏覽器發來的一致 d二、使用密鑰加密消息,回送 若是計算法hash值一致,握手成功
44,RabbitMQ消息堆積怎麼處理?
答:
增長消費者的處理能力(例如優化代碼),或減小發布頻率 單純升級硬件不是辦法,只能起到一時的做用 考慮使用隊列最大長度限制,RabbitMQ 3.1支持 給消息設置年齡,超時就丟棄 默認狀況下,rabbitmq消費者爲單線程串行消費,設置併發消費兩個關鍵屬性concurrentConsumers和prefetchCount,concurrentConsumers設置的是對每一個listener在初始化的時候設置的併發消費者的個數,prefetchCount是每次一次性從broker裏面取的待消費的消息的個數 創建新的queue,消費者同時訂閱新舊queue 生產者端緩存數據,在mq被消費完後再發送到mq 打破發送循環條件,設置合適的qos值,當qos值被用光,而新的ack沒有被mq接收時,就能夠跳出發送循環,去接收新的消息;消費者主動block接收進程,消費者感覺到接收消息過快時主動block,利用block和unblock方法調節接收速率,當接收線程被block時,跳出發送循環。 新建一個topic,partition是原來的10倍;而後寫一個臨時的分發數據的consumer程序,這個程序部署上去消費積壓的數據,消費以後不作耗時的處理,直接均勻輪詢寫入臨時創建好的10倍數量的queue;接着臨時徵用10倍的機器來部署consumer,每一批consumer消費一個臨時queue的數據;等快速消費完積壓數據以後,得恢復原先部署架構,從新用原先的consumer機器來消費消息; 45,RabbitMQ的消息丟失解決方案?
答:
消息持久化:Exchange 設置持久化:durable:true;Queue 設置持久化;Message持久化發送。 ACK確認機制:消息發送確認;消息接收確認。 46,負載均衡算法?
常見6種負載均衡算法:輪詢,隨機,源地址哈希,加權輪詢,加權隨機,最小鏈接數。
nginx5種負載均衡算法:輪詢,weight,ip_hash,fair(響應時間),url_hash
dubbo負載均衡算法:隨機,輪詢,最少活躍調用數,一致性Hash
47,JVM內存區域劃分?
答:
堆:Java中的堆是用來存儲對象自己的以及數組(固然,數組引用是存放在Java棧中的),是Java垃圾收集器管理的主要區域。堆是被全部線程共享的,在JVM中只有一個堆。 虛擬機棧:虛擬機棧中存放的是一個個的棧幀,每一個棧幀對應一個被調用的方法,在棧幀中包括局部變量表、操做數棧、指向當前方法所屬的類的運行時常量池的引用、方法返回地址和一些額外的附加信息。當線程執行一個方法時,就會隨之建立一個對應的棧幀,並將創建的棧幀壓棧。當方法執行完畢以後,便會將棧幀出棧。 本地方法棧:本地方法棧則是爲執行本地方法(Native Method)服務的,在HotSopt虛擬機中直接就把本地方法棧和Java棧合二爲一 方法區:方法區與堆同樣,是被線程共享的區域。方法區存儲了類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯後的代碼等。在方法區中有一個很是重要的部分就是運行時常量池,它是每個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM後,對應的運行時常量池就被建立出來。固然並不是Class文件常量池中的內容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,好比String的intern方法。當方法區沒法知足內存分配需求時,則拋出OutOfMemoryError異常。在HotSpot虛擬機中,用永久代來實現方法區,將GC分代收集擴展至方法區,可是這樣容易遇到內存溢出的問題。JDK1.7中,已經把放在永久代的字符串常量池移到堆中。JDK1.8撤銷永久代,引入元空間。 程序計數器(線程私有):是當前線程所執行的字節碼的行號指示器,每條線程都要有一個獨立的程序計數器,這類內存也稱爲「線程私有」的內存。正在執行java方法的話,計數器記錄的是虛擬機字節碼指令的地址(當前指令的地址)。若是仍是Native方法,則爲空。 直接內存:在JDK1.4中新加入的NOI類,引入了一種基於通道與緩衝區的I/O方式,它能夠使用Native函數直接分配堆外內存,而後經過一個存儲在Java堆中的DirectByteBuffer對象做爲這塊內存的引用進行操做。 48,jvm YGC和FGC發生的具體場景?
答:
正在處理的實現事務功能,下次自動回滾。
隊列實現持久化儲存,下次啓動自動載入。
添加標誌位,未處理 0,處理中 1,已處理 2。每次啓動的時候,把全部狀態爲 1 的,置爲 0。
關鍵性的應用就給電腦配個 UPS。
YGC :對新生代堆進行gc。頻率比較高,由於大部分對象的存活壽命較短,在新生代裏被回收。性能耗費較小。 FGC :全堆範圍的gc。默認堆空間使用到達80%(可調整)的時候會觸發fgc。以咱們生產環境爲例,通常比較少會觸發fgc,有時10天或一週左右會有一次。
YGC發生場景:edn空間不足 FGC發生場景:old空間不足,perm空間不足,調用方法System.gc() ,ygc時的悲觀策略, dump live的內存信息時(jmap –dump:live)
49,一個線程池正在處理服務若是突然斷電該怎麼辦?
答:
隊列實現持久化儲存,下次啓動自動載入。 可是實際須要看狀況,大致思路是這樣。 添加標誌位,未處理 0,處理中 1,已處理 2。每次啓動的時候,把全部狀態爲 1 的,置爲 0。或者定時器處理 關鍵性的應用就給電腦配個 UPS。
50,SpringBoot的優勢?
答:
快速構建項目,極大的提升了開發、部署效率。 對主流開發框架的無配置集成。 項目可獨立運行,無須外部依賴Servlet容器。 提供運行時的應用監控。
51,DoS,DDoS,DRDoS攻擊分別是什麼?
答:DoS是Denial of Service的簡寫就是拒絕服務。
DDoS就是Distributed Denial of Service的簡寫就是分佈式拒絕服務。
DRDoS就是Distributed Reflection Denial of Service的簡寫,分佈反射式拒絕服務。
DoS、DDos以及DRDoS攻擊手段和防範措施 52,服務限流的方式?
答:
漏桶:水(請求)先進入到漏桶裏,漏桶以必定的速度出水(接口有響應速率),當水流入速度過大會直接溢出(訪問頻率超過接口響應速率),而後就拒絕請求。 令牌桶算法:系統會按恆定1/QPS時間間隔(若是QPS=100,則間隔是10ms)往桶裏加入Token,若是桶已經滿了就再也不加了.新請求來臨時,會各自拿走一個Token,若是沒有Token就拒絕服務。 基於redis實現的限流:假設每分鐘訪問次數不能超過10次,在Redis中建立一個鍵,過時60秒,對此服務接口的訪問就把鍵值加1,在60秒內增長到10的時候,禁止訪問服務接口。 計數器,滑動窗口 53,Quartz實現原理?
答:A、scheduler是一個計劃調度器容器(總部),容器裏面能夠盛放衆多的JobDetail和trigger,當容器啓動後,裏面的每一個JobDetail都會根據trigger循序漸進自動去執行。 B、JobDetail是一個可執行的工做,它自己多是有狀態的。 C、Trigger表明一個調度參數的配置,何時去調。 D、當JobDetail和Trigger在scheduler容器上註冊後,造成了裝配好的做業(JobDetail和Trigger所組成的一對兒),就能夠伴隨容器啓動而調度執行了。 E、scheduler是個容器,容器中有一個線程池,用來並行調度執行每一個做業,這樣能夠提升容器效率。
54,數據庫的鎖?
答:行鎖(共享鎖和排他鎖),表鎖,頁級鎖,頁級鎖,意向鎖,讀鎖,寫鎖,悲觀鎖,樂觀鎖等
55,簡述ThreadPoolExecutor內部工做原理?
答:
先查看當前運行狀態,若是不是RUNNING 狀態會拒絕執行任務,若是是RUNNING狀態,就會查看當前運行的線程數量,若是小於核心線程數,會建立新的線程來執行這個任務,若是不小於核心線程,會將這個任務放到阻塞隊列去等代執行,直到上一個任務執行完再來執行這個任務。若是失敗會建立一個非核心線程來執行這個任務若是當前線程數大於最大線程數,會直接拒絕該任務。
56,彙集索引和非彙集索引的區別?
答:
彙集索引: 索引中鍵值的邏輯順序決定了表中相應行的物理順序(索引中的數據物理存放地址和索引的順序是一致的),能夠這麼理解:只要是索引是連續的,那麼數據在存儲介質上的存儲位置也是連續的。 比方說:想要到字典上查找一個字,咱們能夠根據字典前面的拼音找到該字,注意拼音的排列時有順序的。 彙集索引就像咱們根據拼音的順序查字典同樣,能夠大大的提升效率。在常常搜索必定範圍的值時,經過索引找到第一條數據,根據物理地址連續存儲的特色,而後檢索相鄰的數據,直到到達條件截至項。 非彙集索引 索引的邏輯順序與磁盤上的物理存儲順序不一樣。非彙集索引的鍵值在邏輯上也是連續的,可是表中的數據在存儲介質上的物理順序是不一致的,即記錄的邏輯順序和實際存儲的物理順序沒有任何聯繫。索引的記錄節點有一個數據指針指向真正的數據存儲位置。 總結以下: 若是一個主鍵被定義了,那麼這個主鍵就是做爲彙集索引 若是沒有主鍵被定義,那麼該表的第一個惟一非空索引被做爲彙集索引 若是沒有主鍵也沒有合適的惟一索引,那麼innodb內部會生成一個隱藏的主鍵做爲彙集索引,這個隱藏的主鍵是一個6個字節的列,改列的值會隨着數據的插入自增。 InnoDB引擎會爲每張表都加一個彙集索引,而彙集索引指向的的數據又是以物理磁盤順序來存儲的,自增的主鍵會把數據自動向後插入,避免了插入過程當中的彙集索引排序問題。若是對彙集索引進行排序,這會帶來磁盤IO性能損耗是很是大的。
57,java併發包下有哪些類?
答:ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentNavigableMap
CopyOnWriteArrayList
BlockingQueue,BlockingDeque (ArrayBlockingQueue,LinkedBlockingDeque,LinkedBlockingQueue,DelayQueue,PriorityBlockingQueue,SynchronousQueue)
ConcurrentLinkedDeque,ConcurrentLinkedQueue,TransferQueue,LinkedTransferQueue
CopyOnWriteArraySet,ConcurrentSkipListSet
CyclicBarrier,CountDownLatch
Lock(ReetrantLock,ReetrantReadWriteLock)
Atomic包
58,threadlocal爲何會出現oom?
答:ThreadLocal裏面使用了一個存在弱引用的map, map的類型是ThreadLocal.ThreadLocalMap. Map中的key爲一個threadlocal實例。這個Map的確使用了弱引用,不過弱引用只是針對key。每一個key都弱引用指向threadlocal。 當把threadlocal實例置爲null之後,沒有任何強引用指向threadlocal實例,因此threadlocal將會被gc回收。 可是,咱們的value卻不能回收,而這塊value永遠不會被訪問到了,因此存在着內存泄露。由於存在一條從current thread鏈接過來的強引用。只有當前thread結束之後,current thread就不會存在棧中,強引用斷開,Current Thread、Map value將所有被GC回收。最好的作法是將調用threadlocal的remove方法。
在ThreadLocal的get(),set(),remove()的時候都會清除線程ThreadLocalMap裏全部key爲null的value,可是這些被動的預防措施並不能保證不會內存泄漏:
(1)使用static的ThreadLocal,延長了ThreadLocal的生命週期,可能致使內存泄漏。 (2)分配使用了ThreadLocal又再也不調用get(),set(),remove()方法,那麼就會致使內存泄漏,由於這塊內存一直存在。
59,mysql數據庫鎖表怎麼解決?
答:查詢鎖表信息 當前運行的全部事務 select * from information_schema.innodb_trx 當前出現的鎖 select * from information_schema.innodb_locks 鎖等待的對應關係 select * from information_schema.innodb_lock_waits
經過 select * from information_schema.innodb_trx 查詢 trx_mysql_thread_id而後執行 kill 線程ID KILL 8807;//後面的數字即時進程的ID
60,java 判斷對象是不是某個類的類型方法?
instanceof 運算符是用來在運行時指出對象是不是特定類的一個實例。instanceof經過返回一個布爾值來指出,這個對象是不是這個特定類或者是它的子類的一個實例。 getClass判斷,如o.getClass().equals(ClassA.class)。(使用instanceof來判斷一個對象是否是屬於某個類,可是有時候這個類是繼承於一個父類的,因此,不能嚴格判斷出是否是本身的類,而不是本身的父類。) 61,Spring+MyBatis實現讀寫分離簡述?
答:
方案一:經過MyBatis配置文件建立讀寫分離兩個DataSource,每一個SqlSessionFactoryBean對象的mapperLocations屬性制定兩個讀寫數據源的配置文件。將全部讀的操做配置在讀文件中,全部寫的操做配置在寫文件中。 方案二:經過Spring AOP在業務層實現讀寫分離,在DAO層調用前定義切面,利用Spring的AbstractRoutingDataSource解決多數據源的問題,實現動態選擇數據源 方案三:經過Mybatis的Plugin在業務層實現數據庫讀寫分離,在MyBatis建立Statement對象前經過攔截器選擇真正的數據源,在攔截器中根據方法名稱不一樣(select、update、insert、delete)選擇數據源。 方案四:經過spring的AbstractRoutingDataSource和mybatis Plugin攔截器實現很是友好的讀寫分離,原有代碼不須要任何改變。推薦第四種方案 62,紅黑樹的特色?
答:(1)每一個節點或者是黑色,或者是紅色。 (2)根節點是黑色。 (3)每一個葉子節點(NIL)是黑色。 [注意:這裏葉子節點,是指爲空(NIL或NULL)的葉子節點!] (4)若是一個節點是紅色的,則它的子節點必須是黑色的。 (5)從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點。[這裏指到葉子節點的路徑]
63,kafka消息會不會丟失?
答:Kafka消息發送分同步(sync)、異步(async)兩種方式。默認是使用同步方式,可經過producer.type屬性進行配置;Kafka保證消息被安全生產,有三個選項分別是0,1,-1。 經過request.required.acks屬性進行配置: 0表明:不進行消息接收是否成功的確認(默認值); 1表明:當Leader副本接收成功後,返回接收成功確認信息; -1表明:當Leader和Follower副本都接收成功後,返回接收成功確認信息;
網絡異常 acks設置爲0時,不和Kafka集羣進行消息接受確認,當網絡發生異常等狀況時,存在消息丟失的可能; 客戶端異常 異步發送時,消息並無直接發送至Kafka集羣,而是在Client端按必定規則緩存並批量發送。在這期間,若是客戶端發生死機等狀況,都會致使消息的丟失; 緩衝區滿了 異步發送時,Client端緩存的消息超出了緩衝池的大小,也存在消息丟失的可能; Leader副本異常 acks設置爲1時,Leader副本接收成功,Kafka集羣就返回成功確認信息,而Follower副本可能還在同步。這時Leader副本忽然出現異常,新Leader副本(原Follower副本)未能和其保持一致,就會出現消息丟失的狀況; 以上就是消息丟失的幾種狀況,在平常應用中,咱們須要結合自身的應用場景來選擇不一樣的配置。 想要更高的吞吐量就設置:異步、ack=0;想要不丟失消息數據就選:同步、ack=-1策略
64,kafka的leader副本選舉?
答:若是某個分區patition的Leader掛了,那麼其它跟隨者將會進行選舉產生一個新的leader,以後全部的讀寫就會轉移到這個新的Leader上,在kafka中,其不是採用常見的多數選舉的方式進行副本的Leader選舉,而是會在Zookeeper上針對每一個Topic維護一個稱爲ISR(in-sync replica,已同步的副本)的集合,顯然還有一些副本沒有來得及同步。只有這個ISR列表裏面的纔有資格成爲leader(先使用ISR裏面的第一個,若是不行依次類推,由於ISR裏面的是同步副本,消息是最完整且各個節點都是同樣的)。 經過ISR,kafka須要的冗餘度較低,能夠容忍的失敗數比較高。假設某個topic有f+1個副本,kafka能夠容忍f個不可用,固然,若是所有ISR裏面的副本都不可用,也能夠選擇其餘可用的副本,只是存在數據的不一致。
65,kafka消息的檢索?
答:其實很簡單主要是用二分查找算法,好比咱們要查找一條offest=10000的文件,kafka首先會在對應分區下的log文件裏採用二分查看定位到某個記錄該offest =10000這條消息的log,而後從相應的index文件定位其偏移量,而後拿着偏移量到log裏面直接獲取。這樣就完成了一個消息的檢索過程。
66,RabbitMQ 集羣方式?
答:
1)普通集羣:
以兩個節點(rabbit0一、rabbit02)爲例來進行說明。 rabbit01和rabbit02兩個節點僅有相同的元數據,即隊列的結構,但消息實體只存在於其中一個節點rabbit01(或者rabbit02)中。 當消息進入rabbit01節點的Queue後,consumer從rabbit02節點消費時,RabbitMQ會臨時在rabbit0一、rabbit02間進行消息傳輸,把A中的消息實體取出並通過B發送給consumer。因此consumer應儘可能鏈接每個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點創建物理Queue。不然不管consumer連rabbit01或rabbit02,出口總在rabbit01,會產生瓶頸。當rabbit01節點故障後,rabbit02節點沒法取到rabbit01節點中還未消費的消息實體。若是作了消息持久化,那麼得等rabbit01節點恢復,而後纔可被消費;若是沒有持久化的話,就會產生消息丟失的現象。
2)鏡像集羣:
在普通集羣的基礎上,把須要的隊列作成鏡像隊列,消息實體會主動在鏡像節點間同步,而不是在客戶端取數據時臨時拉取,也就是說多少節點消息就會備份多少份。該模式帶來的反作用也很明顯,除了下降系統性能外,若是鏡像隊列數量過多,加之大量的消息進入,集羣內部的網絡帶寬將會被這種同步通信大大消耗掉。因此在對可靠性要求較高的場合中適用 因爲鏡像隊列之間消息自動同步,且內部有選舉master機制,即便master節點宕機也不會影響整個集羣的使用,達到去中心化的目的,從而有效的防止消息丟失及服務不可用等問題
67,ElasticSearch如何解決深度分頁的問題?
答:使用scroll(有狀態)和search after(無狀態)的遊標方式。
68,java代碼優化(一)
答:儘可能指定類、方法的final修飾符。 儘可能重用對象。 儘量使用局部變量。 及時關閉流。 儘可能減小對變量的重複計算。 儘可能採用懶加載的策略,即在須要的時候才建立。 慎用異常。 不要在循環中使用try...catch...,應該把其放在最外層。 若是能估計到待添加的內容長度,爲底層以數組方式實現的集合、工具類指定初始長度。 當複製大量數據時,使用System.arraycopy()命令。 乘法和除法使用移位操做。 循環內不要不斷建立對象引用。 基於效率和類型檢查的考慮,應該儘量使用array,沒法肯定數組大小時才使用ArrayList。 儘可能使用HashMap、ArrayList、StringBuilder,除非線程安全須要,不然不推薦使用Hashtable、Vector、StringBuffer,後三者因爲使用同步機制而致使了性能開銷。 不要將數組聲明爲public static final。
69,java代碼優化(二)
答:儘可能在合適的場合使用單例。 儘可能避免隨意使用靜態變量。 及時清除再也不須要的會話。 實現RandomAccess接口的集合好比ArrayList,應當使用最普通的for循環而不是foreach循環來遍歷 使用同步代碼塊替代同步方法。 將常量聲明爲static final,並以大寫命名。 不要建立一些不使用的對象,不要導入一些不使用的類。 程序運行過程當中避免使用反射。 使用數據庫鏈接池和線程池。 使用帶緩衝的輸入輸出流進行IO操做。 順序插入和隨機訪問比較多的場景使用ArrayList,元素刪除和中間插入比較多的場景使用LinkedList。 不要讓public方法中有太多的形參。 字符串變量和字符串常量equals的時候將字符串常量寫在前面。 請知道,在java中if (i == 1)和if (1 == i)是沒有區別的,但從閱讀習慣上講,建議使用前者。 不要對數組使用toString()方法。 不要對超出範圍的基本數據類型作向下強制轉型。
70,java代碼優化(三)
答:公用的集合類中不使用的數據必定要及時remove掉。 把一個基本數據類型轉爲字符串,基本數據類型.toString()是最快的方式、String.valueOf(數據)次之、數據+""最慢 使用最有效率的方式去遍歷Map。 對資源的close()建議分開操做。 對於ThreadLocal使用前或者使用後必定要先remove。 切記以常量定義的方式替代魔鬼數字,魔鬼數字的存在將極大地下降代碼可讀性,字符串常量是否使用常量定義能夠視狀況而定。 long或者Long初始賦值時,使用大寫的L而不是小寫的l,由於字母l極易與數字1混淆,這個點很是細節,值得注意。 全部重寫的方法必須保留@Override註解。 推薦使用JDK7中新引入的Objects工具類來進行對象的equals比較,直接a.equals(b),有空指針異常的風險。 循環體內不要使用"+"進行字符串拼接,而直接使用StringBuilder不斷append。 不捕獲Java類庫中定義的繼承自RuntimeException的運行時異常類。 避免Random實例被多線程使用,雖然共享該實例是線程安全的,但會因競爭同一seed致使的性能降低,JDK7以後,能夠使用ThreadLocalRandom來獲取隨機數。 靜態類、單例類、工廠類將它們的構造函數置爲private。
71,單點登陸原理與簡單實現?
答:相比於單系統登陸,sso須要一個獨立的認證中心,只有認證中心能接受用戶的用戶名密碼等安全信息,其餘系統不提供登陸入口,只接受認證中心的間接受權。間接受權經過令牌實現,sso認證中心驗證用戶的用戶名密碼沒問題,建立受權令牌,在接下來的跳轉過程當中,受權令牌做爲參數發送給各個子系統,子系統拿到令牌,即獲得了受權,能夠藉此建立局部會話,局部會話登陸方式與單系統的登陸方式相同。這個過程,也就是單點登陸的原理,用下圖說明
單點登陸天然也要單點註銷,在一個子系統中註銷,全部子系統的會話都將被銷燬,用下面的圖來講明
72,MQ作數據同步也會形成不一致,又須要引入監控,實時計算2個集羣的數據同步,作一致性同步。大部分來講,同步es和solr不要在代碼中去同步,同步失敗沒法保證事務,並且業務耦合。能夠使用Databug和cancel等工具去作代碼解耦,MQ支持重試,存儲失敗後拋出異常下次再處理。數據作異構,對外服務時任意拼裝,MYSQL在半同步複製上作了一些優化,保證了一致性,引入了諸如paxos等主流算法保證強一致性問題。 當DB(監遵從庫),binlog有變化,cancel監聽到時候解析過濾發送MQ(表名字,主鍵等)到變化的實時從庫中查詢數據同步到ES聚合表,MQ能夠重試,系統解耦。事務log挖掘縣城會對DB的事務log監聽,並把這些事件發佈到消息代理。
73,分佈式服務調用能夠實現跟蹤系統,能夠在業務日誌中添加調用鏈ID,各個環節RPC均添加調用時延,QPS等。
非業務組件應該少加入業務代碼,服務調用採用買點,也會採用配置採樣率方式,買點即當前節點的上下文信息,包含TraceId,RPCId,開始結束時間,類型,協議,調用方IP,端口,服務名等,以及其餘異常信息,報文等擴展,日誌採用離線+實時的如flume結合kafka等,應按照TraceId彙總日誌後按RPCId順序整理。
74,Sentinel 工做原理?
答:(1)每一個 Sentinel 以每秒鐘一次的頻率向它所知的 Master,Slave 以及其餘 Sentinel 實例發送一個 PING 命令; (2)若是一個實例(instance)距離最後一次有效回覆 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel 標記爲主觀下線; (3)若是一個 Master 被標記爲主觀下線,則正在監視這個 Master 的全部 Sentinel 要以每秒一次的頻率確認 Master 的確進入了主觀下線狀態; (4)當有足夠數量的 Sentinel(大於等於配置文件指定的值)在指定的時間範圍內確認 Master 的確進入了主觀下線狀態,則 Master 會被標記爲客觀下線; (5)在通常狀況下, 每一個 Sentinel 會以每 10 秒一次的頻率向它已知的全部 Master,Slave 發送 INFO 命令; 當 Master 被 Sentinel 標記爲客觀下線時,Sentinel 向下線的 Master 的全部 Slave 發送 INFO 命令的頻率會從 10 秒一次改成每秒一次; (6)若沒有足夠數量的 Sentinel 贊成 Master 已經下線, Master 的客觀下線狀態就會被移除; (7)若 Master 從新向 Sentinel 的 PING 命令返回有效回覆, Master 的主觀下線狀態就會被移除。
監控( Monitoring ): Redis Sentinel 實時監控主服務器和從服務器運行狀態; 自動故障轉移:若是一個 master 不正常運行了,哨兵能夠啓動一個故障轉移進程,將一個 slave 升級成爲 master,其餘的 slave 被從新配置使用新的 master,而且應用程序使用 Redis 服務端通知的新地址;
75,高性能統計UV的方式?
(1)使用redis的set集合
(2)使用redis的bitmap(注意內存消耗)
76,Hbase二級索引,索引海量數據實現方案?
答:
(1) 方案1:使用開源的hbase-indexer,是藉助於hbase的WAL實現,不會影響hbase性能
https://blog.csdn.net/xiahoujie_90/article/details/53400044
(2) 方案2:基於ES本身實現,利用habse的協處理器實現,會影響hbase性能
關鍵注意點:由於數據是存在Hbase中,ES充當的是索引角色,因此在建立ES的mapping時,
應指定_source爲enabled:false。關閉存儲原始文檔。
https://wenku.baidu.com/view/422722fdd0f34693daef5ef7ba0d4a7303766c71.html
77,Elasticsearch分片使用優化?
答:(1)拆分集羣 對於存在明顯分界線的業務,能夠按照業務、地域使用不一樣集羣,這種拆分集羣的思路是很是靠譜的。對於咱們的場景,已經按照地域拆分了集羣,且同一地域的子業務間分界線不明顯,拆分過多的集羣維護成本較高。 (2)調整滾動週期 根據保留時長調整index滾動週期是最簡單有效的思路。例如保留3天的數據按天滾動,保留31天的數據按周滾動,保留一年的數據按月滾動。合理的滾動週期,能夠在存儲成本增長不大的狀況下,大幅下降分片數量。 對於咱們的場景,大部分數據保留31天,在按周滾動的狀況下,集羣的總分片數能夠降低到6.5w~個。 (3)合理設置分片數和副本數 除個別子業務壓力較高外,大部分業務壓力較小,合理設置單Index的分片數效果也不錯。咱們的經驗是單個分片的大小在10GB~30GB之間比較合適,對於壓力很是小的業務能夠直接分配1個分片。其餘用戶可結合具體場景考慮,同時注意單分片的記錄條數不要超過上限2,147,483,519。 在平衡咱們的業務場景對數據可靠性的要求 及 不一樣副本數對存儲成本的開銷 兩個因素以後,咱們選擇使用一主一從的副本策略。 目前咱們集羣單Index的平均分配數爲3,集羣的總分片數降低到3w~個。 (4)分片分配流程優化 默認狀況下,ES在分配分片時會考慮分片relocation對磁盤空間的影響。在分片數較少時,這個優化處理的反作用不明顯。但隨着單機分片數量的上升,這個優化處理涉及的多層循環嵌套過程耗時愈發明顯。可經過cluster.routing.allocation.disk.include_relocations: false關閉此功能,這對磁盤均衡程度影響不明顯。 (5)預建立Index 對於單集羣3w分片的場景,集中在每週某天0點建立Index,對集羣的壓力仍是較大,且存儲空間存在波動。考慮到集羣的持續擴展能力和可靠性,咱們採用預建立方式提早建立分片,並把按Index的建立時間均勻打散到每週的每一天。 (6)持續調整分片數 對於集羣分片的調整,一般不是一蹴而就的。隨着業務的發展,不斷新增的子業務 或 原有子業務規模發生突變,都須要持續調整分片數量。 默認狀況下,新增的子業務會有默認的分片數量,若是不足,會在測試階段及上線初期及時發現。隨着業務發展,系統會考慮Index近期的數據量、寫入速度、集羣規模等因素,動態調整分片數量。
###78,如何編寫高質量代碼151建議?
答: 1、Java開發中通用的方法和準則 不要在常量和變量中出現易混淆的字母; 莫讓常量蛻變成變量; 三元操做符的類型務必一致; 避免帶有變長參數的方法重載; 別讓null值和空值威脅到變長方法; 覆寫變長方法也要循規蹈矩; 警戒字增的陷阱; 不要讓舊語法困擾你; 少用靜態導入; 不要在本類中覆蓋靜態導入的變量和方法; 養成良好習慣,顯示聲明UID; 避免用序列化類在構造函數中爲不變量賦值; 避免爲final變量複雜賦值; 使用序列化類的私有方法巧妙解決部分屬性持久化問題; break萬萬不可忘; 易變業務使用腳本語言編寫; 慎用動態編譯; 避免instantceof非預期結果; 斷言對決不是雞肋; 不要只替換一個類; 2、基本類型 使用偶判斷,不用奇判斷; 用整數類型處理貨幣; 不要讓類型默默轉換; 邊界,邊界,仍是邊界; 不要讓四捨五入虧了一方; 提防包裝類型的null值; 謹慎包裝類型的大小比較; 優先使用整型池; 優先選擇基本類型; 不要隨便設置隨機種子; 3、類、對象及方法 在接口中不要存在實現代碼; 靜態變量必定要先聲明後賦值; 不要覆寫靜態方法; 構造函數儘可能簡化; 避免在構造函數中初始化其餘類; 使用構造代碼塊精煉程序; 使用靜態內部類提供封裝性; 使用匿名類的構造函數; 匿名類的構造函數很特殊; 讓多重繼承成爲現實; 讓工具類不可實例化; 避免對象的淺拷貝; 推薦使用序列化實現對象的拷貝; 覆寫equals方法時不要識別不出本身; equals應該考慮null值情景; 在equals中使用getClass進行類型判斷; 覆寫equals方法必須覆寫hashCode方法; 推薦覆寫toString方法; 使用package-info類爲包服務; 不要主動進行垃圾回收; 4、字符串 推薦使用String直接量賦值; 注意方法中傳遞的參數要求; 正確使用String、StringBuffer、StringBuilder; 注意字符串的位置; 自由選擇字符串拼接方法; 推薦在複雜字符串操做中使用正則表達式; 強烈建議使用UTF編碼; 對字符串排序持一種寬容的心態; 5、數組和集合 性能考慮,數組是首選; 如有必要,使用變長數組; 警戒數組的淺拷貝; 在明確的場景下,爲集合指定初始容量; 多種最值方法,適時選擇; 避開基本類型數組轉換列表陷阱; asList方法產生的List對象不可更改; 不一樣的列表選擇不一樣的遍歷方法; 頻繁插入和刪除時使用LinkedList; 列表相等只需關心元素數據; 推薦使用subList處理局部列表; 生成子表後不要再操做原列表; 使用Comparator進行排序; 不推薦使用binarySearch對列表進行檢索; 集合中的元素必須作到compareTo和equals同步; 集合運算時使用更優雅的方式; 使用shuffle大亂列表; 減小HashMap中元素的數量; 集合中的哈希碼不要重複; 多線程使用Vector或者HashTable; 非穩定排序推薦使用List; 6、枚舉和註解 推薦使用枚舉定義常量; 使用構造函數協助描述枚舉項; 當心switch帶來的空值異常; 在switch的default代碼塊中增長AssertionError錯誤; 使用valueOf前必須進行校驗; 用枚舉實現工廠方法模式更簡潔; 枚舉項的數量限制在64個之內; 當心註解繼承; 枚舉和註解結合使用威力更大; 注意@Override不一樣版本的區別; 7、枚舉和註解 Java的泛型是類型擦除的; 不能初始化泛型參數和數組; 強制聲明泛型的實際類型; 不一樣的場景使用不一樣的泛型通配符; 警戒泛型是不能協變和逆變的; 建議採用的順序是List<T>、List<?>、List<Object>; 嚴格限定泛型類型採用多重界限; 數組的真實類型必須是泛型類型的子類型; 注意Class類的特殊性; 適時選擇getDeclaredXXX和getXXX; 反射訪問屬性或方法時將Accessible設置爲true; 使用forName動態加載類文件; 動態加載不合適數組; 動態代理能夠使代理模式更加靈活; 反射讓模板方法模式更強大; 不須要太多關注反射效率; 8、異常 提倡異常封裝; 採用異常鏈傳遞異常; 受檢異常儘量轉化爲非受檢異常; 不要在finally塊中處理返回值; 使用Throwable獲取棧信息; 異常只爲異常服務; 多使用異常,把性能問題放一邊; 9、多線程和併發 不推薦覆寫start方法; 啓動線程前stop方法是不可靠的; 不使用stop方法中止線程; 線程優先級只使用三個等級; 使用線程異常處理器提高系統可靠性; volatile不能保證數據同步; 異步運算多考慮使用Callable接口; 優先選擇線程池; 適時選擇不一樣的線程池來實現; Lock與synchronized是不同的; 預防線程死鎖; 適當設置阻塞隊列長度; 使用CountDownLatch協調子線程; CyclicBarrier讓多線程齊步走;