String,StringBuffer,SrtingBuilder的區別java
目錄 面試
java異常
異常處理機制主要回答了三個問題算法
- what:異常類型回答了什麼被拋出
- where:異常堆棧跟蹤回答了在哪拋出
- why:異常信息回答了爲何拋出
Java的異常體系
RuntimeException:不可預知的,程序應當自行避免編程
- NullpointException——空指針異常
- ClassCastException——類型強制轉換異常
- IllegalArragumentException——傳遞非法參數異常
- IndexOutOfBoundsException——下標越界異常
- NumberFormatException——數字格式異常
非RuntimeException:可預知的,從編譯器校驗的異常數組
- ClassNotFoundException——找不到指定的class的異常
- IOException——IO操做異常
Error安全
- NoClassDefFoundError——找不到class定義的異常
- StackOverflowError——深遞歸致使棧被耗盡而拋出的異常
- OutOfMemoryError——內存溢出異常
NoClassDefFoundError的成因:數據結構
- 類依賴的class或者jar不存在
- 類文件存在,可是存在不一樣的域中
- 大小寫問題,javac編譯的時候是無視大小寫的,頗有可能編譯出來的class文件就與想要的不同
從責任角度看:多線程
- Error屬於JVM須要負擔的責任
- RuntimeException是程序應該承擔的責任
- Check Exception可檢查異常是Java編譯器應該負擔的責任
Error和Exception的區別
從概念角度解析Java的異常處理機制併發
- Error:程序沒法處理的系統錯誤,編譯器不檢查
- Exception:程序能夠處理的異常,捕獲後可能恢復
- 總結:前者是程序沒法處理的錯誤,後者是能夠處理的異常
Java的異常處理機制
拋出異常:建立異常對象,交由運行時系統處理app
在用戶看來,應用系統發生的全部異常都是應用系統內部的異常
- 設計一個通用的繼承自RuntimeException的異常來同一處理
- 其他異常都統一譯爲上述異常AppException
- 在catch以後,拋出上述異常的子類,並提供足以定位的信息
Java異常處理消耗性能的地方
- try-catch塊印象概念股JVM的優化
- 異常對象實例須要保存棧快照等信息,開銷較大
Java集合框架
工做中消失而面試卻長存的算法與數據結構
數據結構考點
- 數組和鏈表的區別
- 鏈表的操做,如反轉,鏈表環路檢測,雙向鏈表,循環鏈表相關操做
- 隊列,棧的應用
- 二叉樹的遍歷方式及其遞歸和非遞歸的實現
- 紅黑樹的旋轉
算法考點
- 內部排序:如遞歸排序、交換排序(冒泡、快排)、選擇排序、插入排序
- 外部排序:應掌握如何利用有限的內存配合海量的外部存儲來處理超大的數據集,寫不出也要有相關的思路
HashMap、HashTable、ConccurentHashMap
HashMap(Java8之前):數組+鏈表
hash(key.hashCode())%len
HashMap(Java8及之後):數組+鏈表+紅黑樹
性能從O(n)提升到O(logn)
如何優化Hashtable?
早期的ConcurrentHashMap:經過分段鎖Segment來實現
數據+鏈表
ConcurrentHashMap
當前的ConcurrentHashMap:CAS+synchronized使鎖更細化
數組+鏈表+紅黑樹
ConcurrentHashMap:put方法的邏輯
- 判斷Node[]數組是否初始化,沒有則進行初始化操做
- 經過hash定位數組的索引座標,是否有Node節點,若是沒有則使用CAS進行添加(鏈表的頭結點),添加失敗則進入下次循環
- 檢查到內部正在擴容,就幫助它一塊擴容
- 若是f!=null,則使用synchronized鎖住f元素(鏈表/紅黑二叉樹的頭元素)
- 若是是Node(鏈表結構)則執行鏈表ode添加操做
- 若是是TreeNode(樹形結構)則執行樹添加操做
- 判斷鏈表長度已經達到臨界值,固然這個8是默認值,你們也能夠去作調整,當節點數超過這個值就須要把鏈表轉換爲樹結構
ConcurrentHashMap總結:比起Segment,鎖拆的更細
- 首先使用無鎖操做CAS插入頭結點,失敗則循環重試
- 若頭結點已存在,則嘗試獲取頭結點的同步鎖,再進行操做
ConcurrentHashMap:注意
- size()和mappingCount()的一桶,二者計算是否準確
- 多線程環境下如何進行擴容
三者的區別
- HashMap線程不安全,數組+鏈表+紅黑樹
- Hashtable線程安全,鎖住整個對象,數組+鏈表
- ConcurrentHashMap線程安全,CAS+同步鎖,數組+鏈表+紅黑樹
- HashMap的key、value都可爲null,而其餘的兩個類不支持
Java.util.concurrent:提供了併發編程的解決方案
- CAS是java.util.concurrent.atomic包的基礎
- AQS是java.util.concurrent.locks包以及一些經常使用類好比Semophore,ReentrantLock等類的基礎
J.U.C包的分類
- 線程執行器executor
- 鎖locks
- 原子變量類atomic
- 併發工具類tools
- 併發集合collections
CountDownLatch:讓主線程等待一組時間後繼續執行
- 事件指的是CountDownLatch裏的countDown()
CyclicBarrier:阻塞當前線程,等待其餘線程
- 等待其餘線程,且會阻塞本身當前線程,全部線程必須同時到達柵欄位置後,才能繼續執行
- 全部線程到達柵欄處,能夠觸發執行另外一個預先設置的線程
Semaphore:控制某個資源可被同時訪問的線程個數
BlockingQueue:提供可阻塞的入隊和出隊操做
主要用於生產者-消費者模式,在多線程場景時生產者線程在隊列尾部添加元素,而消費者線程則在隊列頭部消費元素,經過這種方式可以到達將任務的生產和消費進行隔離的目的
- ArrayBlockingQueue:一個由數組結構組成的有界阻塞隊列
- LinkedBlockingQueue:一個由鏈表結構組成的有界/無界阻塞隊列
- PriorityBlockingQueue:一個支持優先級排序的無界阻塞隊列
- DealyQueue:一個使用優先級隊列實現的無界阻塞隊列
- SynchronousQueue:一個不存儲元素的阻塞隊列
- LinkedTransferQueue:一個由鏈表結構哦組成的無界阻塞隊列
- LinkedBlockingQueue:一個由鏈表結構組成的雙向阻塞隊列
Java的IO機制
BIO、NIO、AIO
Block-IO:InputStream和OutputStream,Reader和Writer
NonBlock-IO:構建多路複用的、同步非阻塞的IO操做
NIO的核心
- Channels
- FileChannel
- transferTo:把FileChannel中的數據拷貝到另外一個Channel
- transferFrom:把另外一個Channel中的數據拷貝到FileChannel避免了兩次用戶態鉅額內核態間的上下文切換,即「零拷貝」,效率較高
- DatagramChannel
- SocketChannel
- ServerSocketChannel
- Buufers
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
- MappedByteBuffer
- Seletors
select、poll、epoll的區別
支持一個進程所能打開的最大鏈接數
FD劇增後帶來的IO效率問題
Asynchronus IO:基於時間和回到機制
AIO如何進一步加工處理結果
- 基於回調:實現ComplerionHandlerj接口,調用時觸發回調函數
- 返回Future:經過isDone()查看是否準備好,經過get()等待返回數據