參考:
1.http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html
本文為本人學習時記錄, **不做詳細介紹** 里面內容都來源于網上,所有引用都會在頭部聲明,如有侵權還望告知,本人將即時做出修改
1.volatile:
每個線程運行時都有一個線程棧,它保存了線程運行時的變量,當一個線程訪問一個對象時,首先通過對象的引用找到其對應在堆內存的變量值,然后把變量的具體值load到該線程的線程棧中,之后線程就和對象在堆內存的變量值沒有關系了,而是直接修改副本變量的值,修改完成后某一時刻(線程退出前),自動把線程變量副本的值回寫到對象在堆中的變量。
volatile修飾的變量,jvm虛擬機只是保證從主內存加載到線程工作內存的值是最新的,并不能規避并發問題。
例如假如線程1,線程2 在進行read,load 操作中,發現主內存中count的值都是5,那么都會加載這個最新的值,在線程1堆count進行修改之后,會write到主內存中,主內存中的count變量就會變為6,線程2由于已經進行read,load操作,在進行運算之后,也會更新主內存count的變量值為6,導致兩個線程即使用volatile關鍵字修改之后,還是會存在并發的情況。
2.synchronized:
同一個對象的同步代碼塊(一個或多個),同一時間內只能有一個線程訪問,其他線程的訪問(無論是該同步代碼塊還是該對象其他同步代碼塊)都處于阻塞狀態直到先前線程訪問結束,此時,其他線程仍可以訪問該對象的非同步代碼塊,synchronized同時修飾一個類的靜態方法和非靜態方法,線程訪問,一個獲取的是類鎖、一個是獲取的對象鎖,互不干擾,可以同時訪問,同樣一個線程可以同時獲得這兩個鎖。
- 修飾一個代碼塊,作用的對象是調用這個代碼塊的對象
- 修飾一個方法,作用的對象是調用這個方法的對象
- 修飾一個靜態方法,作用的對象是這個類的所有對象
- 修改一個類,作用的對象是這個類的所有對象
3.wait+notify+notifyAll
線程協作-生產者/消費者問題。這三個方法都是Object的方法,調用wait將釋放鎖,notify隨機喚醒一個線程,notifyAll喚醒所有線程。
在調用wait方法時,都是用while判斷條件的,而不是if,在wait方法說明中,也推薦使用while,因為在某些特定的情況下,線程有可能被假喚醒,使用while會循環檢測更穩妥。wait和notify方法必須工作于synchronized內部,且這兩個方法只能由鎖對象來調用。
4.線程中斷、線程讓步、線程睡眠、線程合并、線程優先級
-
線程中斷
- void interrupt()中斷線程,并不是真正停止線程執行,只是設置狀態為true,如果線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程中受阻,則其中斷狀態將被清除,它還將收到一個 InterruptedException;
- static boolean interrupted()判斷當前線程是否中斷,線程的中斷狀態會由該方法清除,如果連續兩次調用該方法,則第二次調用將返回 false;
- boolean isInterrupted()判斷線程是否中斷,線程的中斷狀態會由該方法清除,如果連續兩次調用該方法,則第二次調用將返回 false。
線程讓步
-static void yield()暫停當前正在執行的線程,并執行其他線程,如果存在synchronized線程同步的話,線程讓步不會釋放鎖(監視器對象)。線程睡眠
-static void sleep(long millis)讓當前線程暫停執行millis毫秒,如果存在synchronized線程同步的話,線程讓步不會釋放鎖(監視器對象)。
-static void sleep(long millis, int nanos)讓當前線程暫停執行millis毫秒 + nanos納秒,如果存在synchronized線程同步的話,線程讓步不會釋放鎖(監視器對象)。線程合并
-void join()等待該線程終止;
-void join(long millis)等待該線程終止的時間最長為 millis毫秒;
-void join(long millis, int nanos)等待該線程終止的時間最長為 millis毫秒 + nanos納秒。
所謂合并就是等待其他線程執行完成,再執行當前線程-
線程優先級
- public static final int MAX_PRIORITY = 10
- public static final int MIN_PRIORITY = 1
- public static final int NORM_PRIORITY = 5
默認為NORM_PRIORITY,優先級高的,獲取CPU調度的機會就大
5.定時任務
Timer和TimerTask,自JDK5之后,可以用ScheduledThreadPoolExecutor來替代Timer。
6.Callable、Future和FutureTask
創建線程的2種方式,一種是直接繼承Thread,另外一種就是實現Runnable接口,這兩種方式的缺點是:在執行完任務后無法獲取執行結果,從JDK5開始,就提供了Callable和Future,通過它們可以在任務執行完畢之后得到任務執行結果。閱讀過Android中AsyncTask源碼的同學應該會發現AsyncTask中也應用了這兩個類。
7.鎖對象Lock
用sychronized修飾的方法或者語句塊在代碼執行完之后鎖自動釋放,而用Lock需要我們手動釋放鎖,所以為了保證鎖最終被釋放(發生異常情況),要把互斥區放在try內,釋放鎖放在finally內。與synchronized的區別
8.Condition
Condition中await()對應Object#wait(),signal()對應Object#notify(),signalAll()對應Object#notifyAll(),Condition與Lock結合使用,通過Lock.newCondition()方法創建與Lock綁定的Condition實例。Lock和Condition的關系就如同 Object.wait(),Object.notify()方法和synchronized一樣,它們都可以配合使用完成對多線程協作的控制。
其他不常用的暫不記載,例如CAS、并行計算的框架Fork/Join、ThreadLocal、BlockingQueue等
技術有限,錯誤的地方還忘大家指出