java 学习资料总结
- 1. java集合深入理解
- 1.1 迭代器的快速失敗機(jī)制 fast-fail
- 1.2 collection 集合
- 1.3 List集合
- 1.3.1 ArrayList
- 1.3.2 LinkList
- 2. Map 綜述
- 2.1 徹頭徹尾理解 HashMap
- 2.2徹頭徹尾理解 LinkedHashMap
- 2.3 徹頭徹尾理解 ConcurrentHashMap
- 2.4 徹頭徹尾理解 HashTable
- 3. java面試錦集
- 4. String
- 1.String
- 2.StringBuilder
- 3. StringBuffer
- 4. 總結(jié)
- 5. 泛型
- 6.注解
- 7.java io
- 7.1 File
- 7.2 字節(jié)流字符流
- 7.3 Pushback流
- 7.4 RandomAccessFile
- 7.5 序列化
- a.序列化算法
- b.反序列化創(chuàng)建對象
- c.自定義序列化
- d.注意事項
- 8 線程
- 8.1 創(chuàng)建線程的三種方式
- 8.2 Daemon線程
- 8.3 interrupt的理解
- 8.4 synchronized volatile
- 8.5 wait notify
- 4. Lock
- 5. 并發(fā)容器
- 6. 偏向鎖,輕量鎖,重量級鎖
- 7 內(nèi)存屏障
- 8 可重入鎖解析 ReentrantLock
- 1.加鎖過程
- 2.解鎖過程
- 9 final
- 10 深拷貝VS淺拷貝
1. java集合深入理解
https://blog.csdn.net/u011240877/article/category/6447444
http://www.cnblogs.com/skywang12345/p/3323085.html
1.1 迭代器的快速失敗機(jī)制 fast-fail
https://blog.csdn.net/chewbee/article/details/78314661
1. 是java集合的一種錯誤檢測機(jī)制
2. 防止一個線程在對集合進(jìn)行迭代時候,另一個線程在結(jié)構(gòu)上對集合進(jìn)行修改,不是單純的修改集合元素值
1.2 collection 集合
https://blog.csdn.net/justloveyou_/article/details/52948661
1.3 List集合
https://blog.csdn.net/justloveyou_/article/details/52955619
1.3.1 ArrayList
a. 內(nèi)部數(shù)據(jù)結(jié)構(gòu)
private transient Object[] elementData; // 瞬時域private int size;b. 擴(kuò)容操作 這是一個public 函數(shù),默認(rèn)每次擴(kuò)容是 1.5倍 + 1
// 調(diào)整數(shù)組容量public void ensureCapacity(int minCapacity) {modCount++;int oldCapacity = elementData.length;if (minCapacity > oldCapacity) {Object oldData[] = elementData;int newCapacity = (oldCapacity * 3)/2 + 1;if (newCapacity < minCapacity)newCapacity = minCapacity;// minCapacity is usually close to size, so this is a win:// 最終會調(diào)用 System.ArrayCopy() 這是一個內(nèi)存塊拷貝函數(shù)elementData = Arrays.copyOf(elementData, newCapacity);}}c. 序列化 雖然內(nèi)部數(shù)據(jù)結(jié)構(gòu)一個是瞬態(tài)數(shù)據(jù)和一個基本數(shù)據(jù)類型 ,但是通過自定義的readObject()/writeObject()
private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{// Write out element count, and any hidden stuffint expectedModCount = modCount;s.defaultWriteObject();// Write out size as capacity for behavioural compatibility with clone()s.writeInt(size);// Write out all elements in the proper order.for (int i=0; i<size; i++) {s.writeObject(elementData[i]);}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}}private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {elementData = EMPTY_ELEMENTDATA;// Read in size, and any hidden stuffs.defaultReadObject();// Read in capacitys.readInt(); // ignoredif (size > 0) {// be like clone(), allocate array based upon size not capacityint capacity = calculateCapacity(elementData, size);SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);ensureCapacityInternal(size);Object[] a = elementData;// Read in all elements in the proper order.for (int i=0; i<size; i++) {a[i] = s.readObject();}}}d. ArrayList 允許值為null
// 移除此列表中 “首次” 出現(xiàn)的指定元素(如果存在)。這是因為 ArrayList 中允許存放重復(fù)的元素。 public boolean remove(Object o) { // 由于ArrayList中允許存放null,因此下面通過兩種情況來分別處理。 if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { // 類似remove(int index),移除列表中指定位置上的元素。 fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } }1.3.2 LinkList
a. 頭結(jié)點不存放任何數(shù)據(jù)
b. 新增元素放在鏈表尾部
c. 只能遍歷訪問,不能隨機(jī)訪問
2. Map 綜述
https://blog.csdn.net/justloveyou_/
2.1 徹頭徹尾理解 HashMap
https://blog.csdn.net/justloveyou_/article/details/62893086
初始容量: 桶的數(shù)量
負(fù)載因子: 擴(kuò)容閾值=負(fù)載因子 * 初始容量
迭代器的快速失敗機(jī)制fast-fail機(jī)制
在使用迭代器遍歷Hashmap的過程中,別的線程不允許修改hashmap,要不然就會出現(xiàn)快速失敗,內(nèi)部是通過modCount計算器來實現(xiàn)的.
多線程并發(fā)HashMap,寫操作導(dǎo)致擴(kuò)容
https://www.cnblogs.com/dongguacai/p/5599100.html
https://blog.csdn.net/u013668852/article/details/77141842
2.2徹頭徹尾理解 LinkedHashMap
https://blog.csdn.net/justloveyou_/article/details/71713781
0. 增加屬性: 鏈表頭節(jié)點header , 標(biāo)志位accessOrder,默認(rèn)是保持插入順序
1. 在HashMap的基礎(chǔ)上增加雙向鏈表
2. 默認(rèn)是保持插入順序
3. LUR算法(最近最少使用)
1. HashMap與LinkHashMap 的get/set方法會訪問accessOrder() ,但是HashMap的accessOrder()是空操作
2. LinkHashMap的accessOrder(),如果對應(yīng)的accessOrder設(shè)置為true recordAccess()函數(shù)在訪問內(nèi)部節(jié)點的時候就會把訪問節(jié)點放到隊列的尾部,并刪除當(dāng)前節(jié)點
新增節(jié)點
/*** This override alters behavior of superclass put method. It causes newly* allocated entry to get inserted at the end of the linked list and* removes the eldest entry if appropriate.** LinkedHashMap中的addEntry方法*/void addEntry(int hash, K key, V value, int bucketIndex) { //創(chuàng)建新的Entry,并插入到LinkedHashMap中 createEntry(hash, key, value, bucketIndex); // 重寫了HashMap中的createEntry方法//雙向鏈表的第一個有效節(jié)點(header后的那個節(jié)點)為最近最少使用的節(jié)點,這是用來支持LRU算法的Entry<K,V> eldest = header.after; //如果有必要,則刪除掉該近期最少使用的節(jié)點, //這要看對removeEldestEntry的覆寫,由于默認(rèn)為false,因此默認(rèn)是不做任何處理的。 if (removeEldestEntry(eldest)) { removeEntryForKey(eldest.key); } else { //擴(kuò)容到原來的2倍 if (size >= threshold) resize(2 * table.length); } } void createEntry(int hash, K key, V value, int bucketIndex) { // 向哈希表中插入Entry,這點與HashMap中相同 //創(chuàng)建新的Entry并將其鏈入到數(shù)組對應(yīng)桶的鏈表的頭結(jié)點處, HashMap.Entry<K,V> old = table[bucketIndex]; Entry<K,V> e = new Entry<K,V>(hash, key, value, old); table[bucketIndex] = e; //在每次向哈希表插入Entry的同時,都會將其插入到雙向鏈表的尾部, //這樣就按照Entry插入LinkedHashMap的先后順序來迭代元素(LinkedHashMap根據(jù)雙向鏈表重寫了迭代器)//同時,新put進(jìn)來的Entry是最近訪問的Entry,把其放在鏈表末尾 ,也符合LRU算法的實現(xiàn) e.addBefore(header); size++; }recordAccess() HashMap是一個空函數(shù),LinkHashMap如下所示:
void recordAccess(HashMap<K,V> m) { LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; //如果鏈表中元素按照訪問順序排序,則將當(dāng)前訪問的Entry移到雙向循環(huán)鏈表的尾部, //如果是按照插入的先后順序排序,則不做任何事情。 if (lm.accessOrder) { lm.modCount++; //移除當(dāng)前訪問的Entry remove(); //將當(dāng)前訪問的Entry插入到鏈表的尾部 addBefore(lm.header); } }2.3 徹頭徹尾理解 ConcurrentHashMap
https://blog.csdn.net/justloveyou_/article/details/72783008
a. segment繼承ReentrantLock ,使得對象具備了鎖的功能
b. 初始容量,負(fù)載因子,并發(fā)級別 三個重要參數(shù) . 默認(rèn)值分別為16 , 0.75 , 16
構(gòu)造函數(shù) : 根據(jù)初始容量,并發(fā)級別,確定 多少各segment 以及每個segment多少個桶
public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)throw new IllegalArgumentException();if (concurrencyLevel > MAX_SEGMENTS) concurrencyLevel = MAX_SEGMENTS;// Find power-of-two sizes best matching argumentsint sshift = 0; // 大小為 lg(ssize) int ssize = 1; // 段的數(shù)目,segments數(shù)組的大小(2的冪次方)// 并發(fā)級別可能不是2的冪次方 ,轉(zhuǎn)換一下// 假設(shè)并發(fā)級別是5,那么就會分為8段while (ssize < concurrencyLevel) {++sshift; ssize <<= 1;}segmentShift = 32 - sshift; // 用于定位段segmentMask = ssize - 1; // 用于定位段// this.segments = Segment.newArray(ssize); // 創(chuàng)建segments數(shù)組if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;int c = initialCapacity / ssize; // 總的桶數(shù)/總的段數(shù) = 平均每個段中的桶數(shù)目 ,但是不是 2 冪次方if (c * ssize < initialCapacity)++c;int cap = 1; // 每個段所擁有的桶的數(shù)目(2的冪次方)while (cap < c)cap <<= 1;for (int i = 0; i < this.segments.length; ++i) // 初始化segments數(shù)組this.segments[i] = new Segment<K,V>(cap, loadFactor);}c. put操作
d. get操作
// Segment 類V get(Object key, int hash) {if (count != 0) { // read-volatile,首先讀 count 變量HashEntry<K,V> e = getFirst(hash); // 獲取桶中鏈表頭結(jié)點while (e != null) {if (e.hash == hash && key.equals(e.key)) { // 查找鏈中是否存在指定Key的鍵值對V v = e.value;if (v != null) // 如果讀到value域不為 null,直接返回return v; // 如果讀到value域為null,說明發(fā)生了重排序,加鎖后重新讀取return readValueUnderLock(e); // recheck}e = e.next;}}return null; // 如果不存在,直接返回null }e. rehash操作
f. size() 統(tǒng)計大小操作
g. 與JDK1.8實現(xiàn)的ConcurrentHashMap對比
https://blog.csdn.net/fouy_yun/article/details/77816587
1. 取消了分段
2. 鏈表長度默認(rèn)超過8 ,變成紅黑樹
put操作 部分添加操作加鎖
1. 若table[]未創(chuàng)建,則初始化。 2. 當(dāng)table[i]后面無節(jié)點時,直接創(chuàng)建Node(無鎖操作)。 cas原子操作 3. 如果當(dāng)前正在擴(kuò)容,則幫助擴(kuò)容并返回最新table[]。 4. 然后在鏈表或者紅黑樹中追加節(jié)點。 鎖住當(dāng)前table[i] 5. 最后還回去判斷是否到達(dá)閥值,如到達(dá)變?yōu)榧t黑樹結(jié)構(gòu)。get操作 整個過程都沒有加鎖
1. 首先定位到table[]中的i。 2. 若table[i]存在,則繼續(xù)查找。 3. 首先比較鏈表頭部,如果是則返回。 4. 然后如果為紅黑樹,查找樹。 5. 最后再循環(huán)鏈表查找。2.4 徹頭徹尾理解 HashTable
https://blog.csdn.net/justloveyou_/article/details/72862373
put操作 :
public synchronized V put(K key, V value) { // 加鎖同步,保證Hashtable的線程安全性// Make sure the value is not nullif (value == null) { // 不同于HashMap,Hashtable不允許空的valuethrow new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry tab[] = table;int hash = key.hashCode(); // key 的哈希值,同時也暗示Hashtable不同于HashMap,其不允許空的keyint index = (hash & 0x7FFFFFFF) % tab.length; // 取余計算節(jié)點存放桶位,0x7FFFFFFF 是最大的int型數(shù)的二進(jìn)制表示// 先查找Hashtable上述桶位中是否包含具有相同Key的K/V對for (Entry<K, V> e = tab[index]; e != null; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {V old = e.value;e.value = value;return old;}}// 向Hashtable中插入目標(biāo)K/V對modCount++; // 發(fā)生結(jié)構(gòu)性改變,modCount加1if (count >= threshold) { //在插入目標(biāo)K/V對前,先檢查是否需要擴(kuò)容(不同于HashMap的插入后檢查是否需要擴(kuò)容) // Rehash the table if the threshold is exceededrehash();tab = table;index = (hash & 0x7FFFFFFF) % tab.length; // 擴(kuò)容后,重新計算K/V對插入的桶位}// Creates the new entry.Entry<K, V> e = tab[index];tab[index] = new Entry<K, V>(hash, key, value, e); // 將K/V對鏈入對應(yīng)桶中鏈表,并成為頭結(jié)點count++; // Hashtable中Entry數(shù)目加1return null;}
get操作
3. java面試錦集
https://blog.csdn.net/justloveyou_/article/details/78653660
https://blog.csdn.net/justloveyou_/article/details/78653929
https://blog.csdn.net/justloveyou_/article/details/78313167
4. String
https://blog.csdn.net/justloveyou_/article/details/52556427
https://blog.csdn.net/justloveyou_/article/details/60983034
1.String
對String的一般認(rèn)識2.StringBuilder
3. StringBuffer
4. 總結(jié)
5. 泛型
https://blog.csdn.net/s10461/article/details/53941091
泛型遇上多態(tài)
https://blog.csdn.net/lonelyroamer/article/details/7868820
6.注解
https://blog.csdn.net/briblue/article/details/73824058
https://www.cnblogs.com/Qian123/p/5256084.html
7.java io
7.1 File
7.2 字節(jié)流字符流
7.3 Pushback流
7.4 RandomAccessFile
7.5 序列化
自定義readObject函數(shù)的調(diào)用過程
https://blog.csdn.net/xiaoanian/article/details/9064635
https://www.cnblogs.com/yoohot/p/6019767.html
a.序列化算法
note: 注意可變對象的序列化
b.反序列化創(chuàng)建對象
c.自定義序列化
d.注意事項
8 線程
8.1 創(chuàng)建線程的三種方式
8.2 Daemon線程
8.3 interrupt的理解
https://www.ibm.com/developerworks/cn/java/j-jtp05236.html
https://www.cnblogs.com/timlearn/p/4008783.html
1. java中斷是一種協(xié)調(diào)機(jī)制
2. 線程對象調(diào)用interrupt函數(shù)向線程發(fā)送一個中斷信號
3. 在線程內(nèi)部,如果線程處于阻塞,那么就會拋出InterruptException異常;如果處于運(yùn)行狀態(tài),那么就會設(shè)置一下該線程的中斷狀態(tài)為真
4. isInterrupted()函數(shù)返回線程現(xiàn)在是不是中斷狀態(tài),但是不會影響中斷狀態(tài)
5. interrupted()靜態(tài)函數(shù),會重置中斷狀態(tài)
8.4 synchronized volatile
https://www.cnblogs.com/wq3435/p/6220751.html
https://blog.csdn.net/justloveyou_/article/details/53672005
8.5 wait notify
https://www.cnblogs.com/hapjin/p/5492645.html
線程狀態(tài)轉(zhuǎn)移
https://blog.csdn.net/pange1991/article/details/53860651
問題1: 為什么會假喚醒?
問題2: 為什么需要需要同步?
4. Lock
5. 并發(fā)容器
6. 偏向鎖,輕量鎖,重量級鎖
7 內(nèi)存屏障
http://ifeve.com/disruptor-memory-barrier/
8 可重入鎖解析 ReentrantLock
http://www.cnblogs.com/xrq730/p/4979021.html
https://blog.csdn.net/lsgqjh/article/details/63685058
1.加鎖過程
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) { //如果沒有線程獲取鎖,則當(dāng)前線程CAS獲取鎖。并設(shè)置自己為當(dāng)前鎖的獨(dú)占線程if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {// 如果存在鎖競爭,判斷獲取鎖的線程是否是當(dāng)前線程, 如果是 那么根據(jù)可重入的含義, 使當(dāng)前state+1;int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}如果不是當(dāng)前線程,則不能獲取同步狀態(tài)return false; }state不為0,說明當(dāng)前有線程持有該鎖,那么判斷是不是當(dāng)前線程想重入
2.解鎖過程
protected final boolean tryRelease(int releases) {int c = getState() - releases;// 只有獲得鎖的線程自己才能釋放鎖if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {//c==0說明已經(jīng)無鎖free = true;setExclusiveOwnerThread(null);}setState(c);//否則更新state為state-1, 也就是加鎖多少次,就得釋放多少次, lock unlock配對使用。return free;}9 final
https://www.cnblogs.com/senlinyang/p/7875468.html
1. 寫final域的重排序規(guī)則:禁止把final域的寫重排序到構(gòu)造函數(shù)之外——>對象的引用在任意線程可見之前,final域一定是已經(jīng)正確初始化過的
通過下面2種方式保證
a. JMM禁止編譯器把final域?qū)懼嘏判虻綐?gòu)造函數(shù)之外
b. 編譯器會在final域的寫之后,構(gòu)造函數(shù)return之前,插入一個StoreStore內(nèi)存屏障
2. 讀final域的重排序規(guī)則: 初次讀對象引用和初次讀對象包含的final域兩個操作之間禁止重排序,編譯器會在兩個操作之間插入LoadLoad內(nèi)存屏障——–>在讀一個對象的final域之前,一定會先讀取包含這個final域的對象的引用
3. final域是一個引用類型,final域?qū)ο髢?nèi)部成員的初始化和使用對象之間禁止重排序
final域可以給我們一下保證: 只要對象正確的構(gòu)造,那么不需要同步,任意線程都可以看到final域在構(gòu)造函數(shù)中初始化值
10 深拷貝VS淺拷貝
總結(jié)
以上是生活随笔為你收集整理的java 学习资料总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 秋招算法岗总结
- 下一篇: 最新emoji表情代码大全_2020最新