日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 学习资料总结

發(fā)布時間:2024/8/1 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 学习资料总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  • 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; } }

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ù)載因子 * 初始容量

  • 有兩個重要的數(shù)據(jù): 容量(默認(rèn)是16),負(fù)載因子(默認(rèn)是0.75)
  • 使用數(shù)組鏈表的結(jié)構(gòu)來存儲
  • put操作
  • get操作
  • resize擴(kuò)容操作 多線程的情況下出現(xiàn)死循環(huán)
  • 非線程安全的
  • 迭代器的快速失敗機(jī)制fast-fail機(jī)制

    在使用迭代器遍歷Hashmap的過程中,別的線程不允許修改hashmap,要不然就會出現(xiàn)快速失敗,內(nèi)部是通過modCount計算器來實現(xiàn)的.

  • 多線程并發(fā)HashMap,寫操作導(dǎo)致擴(kuò)容

  • 內(nèi)部的鏈表產(chǎn)生死循環(huán) cpu100%
  • 獲取null
  • 元素丟失
    https://www.cnblogs.com/dongguacai/p/5599100.html
    https://blog.csdn.net/u013668852/article/details/77141842
  • /*** Associates the specified value with the specified key in this map.* If the map previously contained a mapping for the key, the old* value is replaced.** @param key key with which the specified value is to be associated* @param value value to be associated with the specified key* @return the previous value associated with key, or null if there was no mapping for key.* Note that a null return can also indicate that the map previously associated null with key.*/public V put(K key, V value) {//當(dāng)key為null時,調(diào)用putForNullKey方法,并將該鍵值對保存到table的第一個位置 if (key == null)return putForNullKey(value); //根據(jù)key的hashCode計算hash值int hash = hash(key.hashCode()); // ------- (1)//計算該鍵值對在數(shù)組中的存儲位置(哪個桶)int i = indexFor(hash, table.length); // ------- (2)//在table的第i個桶上進(jìn)行迭代,尋找 key 保存的位置for (Entry<K,V> e = table[i]; e != null; e = e.next) { // ------- (3)Object k;//判斷該條鏈上是否存在hash值相同且key值相等的映射,若存在,則直接覆蓋 value,并返回舊valueif (e.hash == hash && ((k = e.key) == key || key.equals(k))) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue; // 返回舊值}}modCount++; //修改次數(shù)增加1,快速失敗機(jī)制//原HashMap中無該映射,將該添加至該鏈的鏈頭addEntry(hash, key, value, i); return null;}

    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); } }
  • 使用LinkHashMap實現(xiàn)LRU算法
  • public class LRU<K,V> extends LinkedHashMap<K, V> {private static final long serialVersionUID = 1L;public LRU(int initialCapacity,float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor, accessOrder);}/* LinkHashMap中的實現(xiàn)就是單純的返回一個false,也就是不刪除節(jié)點protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {return false;} */@Overrideprotected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {// TODO Auto-generated method stubif(size() > 6){return true;}return false;}public static void main(String[] args) {LRU<Character, Integer> lru = new LRU<Character, Integer>(16, 0.75f, true);String s = "abcdefghijkl";for (int i = 0; i < s.length(); i++) {lru.put(s.charAt(i), i);}System.out.println("LRU中key為h的Entry的值為: " + lru.get('h'));System.out.println("LRU的大小 :" + lru.size());System.out.println("LRU :" + lru);} }

    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)計大小操作

  • 不加鎖重試2次,每次去統(tǒng)計segment中的數(shù)量的時候,計入modCount的大小, 所有的段統(tǒng)計完成,去比較一下每個段中的modCount是否產(chǎn)生變化
  • 如果產(chǎn)生變化,那么就對所有的段加鎖,再次統(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

  • Hashtable不同于HashMap,前者既不允許key為null,也不允許value為null;
  • HashMap中用于定位桶位的Key的hash的計算過程要比Hashtable復(fù)雜一點,沒有Hashtable如此簡單、直接;
  • 在HashMap的插入K/V對的過程中,總是先插入后檢查是否需要擴(kuò)容;而Hashtable則是先檢查是否需要擴(kuò)容后插入;
  • Hashtable不同于HashMap,前者的put操作是線程安全的


    put操作 :

  • 方法同步
  • 不允許空value
  • 沒有對key做出null處理,暗示key不能為null
  • 計算桶的位置使用的是取模運(yùn)算,也不是HashMap的&運(yùn)算,也就是說HashTable的初始容量沒有什么要求
  • 先判斷是否需要擴(kuò)容,再插入節(jié)點

  • 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操作

  • 同步方法
  • 取模的方式定位桶位置
  • 在鏈表中查找指定的key ,沒找到返回null
  • public synchronized V get(Object key) { // 不同于HashMap,Hashtable的讀取操作是同步的Entry tab[] = table;int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; // 定位K/V對的桶位for (Entry<K, V> e = tab[index]; e != null; e = e.next) { // 在特定桶中依次查找指定Key的K/V對if ((e.hash == hash) && e.key.equals(key)) {return e.value; }}return null; // 查找失敗}

    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)識
  • 類使用了final修飾,不能被繼承
  • 內(nèi)部字段也被final修飾,初始化就不能再次修改
  • String是一個不可變類,線程安全
  • 內(nèi)部使用的是char[]來表示
  • 編譯期間就會把字面字符串放到字符串常量池 字符串拼接操作
  • 字符串字面量拼接,標(biāo)量替換
  • 字符串引用拼接 ,還是會調(diào)用StringBuilder.append toString返回一個String對象
  • 引用拼接的本質(zhì): String s4 = s1 + s2 + s3; ====> String s4 = (new StringBuilder(String.valueOf(s1))).append(s2).append(s3).toString();

    2.StringBuilder

  • 不是線程安全的類
  • 是單線程下替換StringBuffer的一個類
  • 3. StringBuffer

  • 是一個線程安全的類
  • 4. 總結(jié)

  • 使用字面值形式創(chuàng)建字符串時,不一定會創(chuàng)建對象,但其引用一定指向位于字符串常量池的某個對象;
  • 使用 new String(“…”)方式創(chuàng)建字符串時,一定會創(chuàng)建對象,甚至可能會同時創(chuàng)建兩個對象(一個位于字符串常量池中,一個位于堆中);
  • String 對象是不可變的,對String 對象的任何改變都會導(dǎo)致一個新的 String 對象的產(chǎn)生,而不會影響到原String 對象;
  • StringBuilder 與 StringBuffer 具有共同的父類,具有相同的API,分別適用于單線程和多線程環(huán)境下。特別地,在單線程環(huán)境下,StringBuilder 是 StringBuffer 的替代品,前者效率相對較高;
  • 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.序列化算法

  • 所有的對象都有一個序列化編號
  • 檢查對象是否已經(jīng)被序列化
  • 如果已經(jīng)序列化,那么只輸出序列化編號
  • note: 注意可變對象的序列化

    b.反序列化創(chuàng)建對象

  • 獲取反序列化對象的元數(shù)據(jù)(Class文件) ——> 該類還沒有被加載,那就執(zhí)行類加載機(jī)制
  • 在內(nèi)存中創(chuàng)建內(nèi)存空間
  • 直接內(nèi)存賦值
  • 不需要調(diào)用構(gòu)造函數(shù)
  • c.自定義序列化

  • 實現(xiàn)Serializable接口,該接口就是一個標(biāo)記,內(nèi)部沒有任何東西
  • 實現(xiàn)Externalizable接口
  • d.注意事項

  • 父類實現(xiàn)了序列化,子類自動實現(xiàn)序列化
  • 基類沒有實現(xiàn)序列化
  • 如果 存在無參構(gòu)造函數(shù),那么序列化過程中不會報錯,但是不會保存實例變量值
  • 如果不存在無參構(gòu)造函數(shù),那么序列化過程中直接報錯
  • transient修飾的變量不參與序列化,類變量也不參與序列化
  • 8 線程

    8.1 創(chuàng)建線程的三種方式

  • 繼承Thread
  • 實現(xiàn)Runnable接口
  • 實現(xiàn)Callable接口
  • 8.2 Daemon線程

  • 需要在線程啟動之前設(shè)置為后臺線程,否則線程啟動之后,線程狀態(tài)是Runnable,而在setDaemon函數(shù)中會判斷線程狀態(tài)是不是new狀態(tài),不是就報錯了
  • 所有的前臺線程退出了,那么后臺線程也就退出了
  • Daemon線程中再次創(chuàng)建線程也是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

  • volatile
  • 保證各線程的可見性,但是不保證原子性.線程的工作內(nèi)存馬上同步到主內(nèi)存中
  • 禁止指令重排序
  • 輕量級鎖
    https://www.cnblogs.com/wq3435/p/6220751.html
    https://blog.csdn.net/justloveyou_/article/details/53672005
  • synchronized可以保證
  • 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: 為什么需要需要同步?

    synchronized(object){// 使用while防止假喚醒while(條件不滿足){object.wait();}//邏輯處理; }synchronized(object){//改變條件object.notifyAll(); }
  • 對象的wait notify方法必須在同步快內(nèi)部,也就是說需要獲取對象鎖才可以調(diào)用執(zhí)行
  • notify()執(zhí)行,出了同步快,那么就會喚醒該對象等待隊列上的線程,進(jìn)入同步隊列
  • wait()執(zhí)行,放棄cpu資源,釋放鎖,線程放進(jìn)等待隊列中,等待喚醒
  • 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; }
  • 獲取volatile修飾的state值
  • 如果state的值為0,說明還沒有線程持有鎖
  • 使用CAS操作設(shè)置state的值
  • 設(shè)置當(dāng)前線程持有鎖
  • state不為0,說明當(dāng)前有線程持有該鎖,那么判斷是不是當(dāng)前線程想重入

  • 如果是,重新設(shè)置state的值
  • 如果不是,獲取鎖失敗
  • 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;}
  • 當(dāng)前線程不持有鎖,解鎖異常拋出
  • 獲取state值
  • 如果state的值為0了,那么說明解鎖完就沒有那個對象持有該鎖了,需要設(shè)置鎖沒有持有任何線程
  • 重新設(shè)置state
  • 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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。