參考:
1.http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html
本文為本人學(xué)習(xí)時(shí)記錄, **不做詳細(xì)介紹** 里面內(nèi)容都來(lái)源于網(wǎng)上,所有引用都會(huì)在頭部聲明,如有侵權(quán)還望告知,本人將即時(shí)做出修改
1.volatile:
每個(gè)線程運(yùn)行時(shí)都有一個(gè)線程棧,它保存了線程運(yùn)行時(shí)的變量,當(dāng)一個(gè)線程訪問(wèn)一個(gè)對(duì)象時(shí),首先通過(guò)對(duì)象的引用找到其對(duì)應(yīng)在堆內(nèi)存的變量值,然后把變量的具體值load到該線程的線程棧中,之后線程就和對(duì)象在堆內(nèi)存的變量值沒(méi)有關(guān)系了,而是直接修改副本變量的值,修改完成后某一時(shí)刻(線程退出前),自動(dòng)把線程變量副本的值回寫(xiě)到對(duì)象在堆中的變量。

volatile修飾的變量,jvm虛擬機(jī)只是保證從主內(nèi)存加載到線程工作內(nèi)存的值是最新的,并不能規(guī)避并發(fā)問(wèn)題。
例如假如線程1,線程2 在進(jìn)行read,load 操作中,發(fā)現(xiàn)主內(nèi)存中count的值都是5,那么都會(huì)加載這個(gè)最新的值,在線程1堆count進(jìn)行修改之后,會(huì)write到主內(nèi)存中,主內(nèi)存中的count變量就會(huì)變?yōu)?,線程2由于已經(jīng)進(jìn)行read,load操作,在進(jìn)行運(yùn)算之后,也會(huì)更新主內(nèi)存count的變量值為6,導(dǎo)致兩個(gè)線程即使用volatile關(guān)鍵字修改之后,還是會(huì)存在并發(fā)的情況。
2.synchronized:
同一個(gè)對(duì)象的同步代碼塊(一個(gè)或多個(gè)),同一時(shí)間內(nèi)只能有一個(gè)線程訪問(wèn),其他線程的訪問(wèn)(無(wú)論是該同步代碼塊還是該對(duì)象其他同步代碼塊)都處于阻塞狀態(tài)直到先前線程訪問(wèn)結(jié)束,此時(shí),其他線程仍可以訪問(wèn)該對(duì)象的非同步代碼塊,synchronized同時(shí)修飾一個(gè)類的靜態(tài)方法和非靜態(tài)方法,線程訪問(wèn),一個(gè)獲取的是類鎖、一個(gè)是獲取的對(duì)象鎖,互不干擾,可以同時(shí)訪問(wèn),同樣一個(gè)線程可以同時(shí)獲得這兩個(gè)鎖。
- 修飾一個(gè)代碼塊,作用的對(duì)象是調(diào)用這個(gè)代碼塊的對(duì)象
- 修飾一個(gè)方法,作用的對(duì)象是調(diào)用這個(gè)方法的對(duì)象
- 修飾一個(gè)靜態(tài)方法,作用的對(duì)象是這個(gè)類的所有對(duì)象
- 修改一個(gè)類,作用的對(duì)象是這個(gè)類的所有對(duì)象
3.wait+notify+notifyAll
線程協(xié)作-生產(chǎn)者/消費(fèi)者問(wèn)題。這三個(gè)方法都是Object的方法,調(diào)用wait將釋放鎖,notify隨機(jī)喚醒一個(gè)線程,notifyAll喚醒所有線程。
在調(diào)用wait方法時(shí),都是用while判斷條件的,而不是if,在wait方法說(shuō)明中,也推薦使用while,因?yàn)樵谀承┨囟ǖ那闆r下,線程有可能被假喚醒,使用while會(huì)循環(huán)檢測(cè)更穩(wěn)妥。wait和notify方法必須工作于synchronized內(nèi)部,且這兩個(gè)方法只能由鎖對(duì)象來(lái)調(diào)用。
4.線程中斷、線程讓步、線程睡眠、線程合并、線程優(yōu)先級(jí)
-
線程中斷
- void interrupt()中斷線程,并不是真正停止線程執(zhí)行,只是設(shè)置狀態(tài)為true,如果線程在調(diào)用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過(guò)程中受阻,則其中斷狀態(tài)將被清除,它還將收到一個(gè) InterruptedException;
- static boolean interrupted()判斷當(dāng)前線程是否中斷,線程的中斷狀態(tài)會(huì)由該方法清除,如果連續(xù)兩次調(diào)用該方法,則第二次調(diào)用將返回 false;
- boolean isInterrupted()判斷線程是否中斷,線程的中斷狀態(tài)會(huì)由該方法清除,如果連續(xù)兩次調(diào)用該方法,則第二次調(diào)用將返回 false。
線程讓步
-static void yield()暫停當(dāng)前正在執(zhí)行的線程,并執(zhí)行其他線程,如果存在synchronized線程同步的話,線程讓步不會(huì)釋放鎖(監(jiān)視器對(duì)象)。線程睡眠
-static void sleep(long millis)讓當(dāng)前線程暫停執(zhí)行millis毫秒,如果存在synchronized線程同步的話,線程讓步不會(huì)釋放鎖(監(jiān)視器對(duì)象)。
-static void sleep(long millis, int nanos)讓當(dāng)前線程暫停執(zhí)行millis毫秒 + nanos納秒,如果存在synchronized線程同步的話,線程讓步不會(huì)釋放鎖(監(jiān)視器對(duì)象)。線程合并
-void join()等待該線程終止;
-void join(long millis)等待該線程終止的時(shí)間最長(zhǎng)為 millis毫秒;
-void join(long millis, int nanos)等待該線程終止的時(shí)間最長(zhǎng)為 millis毫秒 + nanos納秒。
所謂合并就是等待其他線程執(zhí)行完成,再執(zhí)行當(dāng)前線程-
線程優(yōu)先級(jí)
- public static final int MAX_PRIORITY = 10
- public static final int MIN_PRIORITY = 1
- public static final int NORM_PRIORITY = 5
默認(rèn)為NORM_PRIORITY,優(yōu)先級(jí)高的,獲取CPU調(diào)度的機(jī)會(huì)就大
5.定時(shí)任務(wù)
Timer和TimerTask,自JDK5之后,可以用ScheduledThreadPoolExecutor來(lái)替代Timer。
6.Callable、Future和FutureTask
創(chuàng)建線程的2種方式,一種是直接繼承Thread,另外一種就是實(shí)現(xiàn)Runnable接口,這兩種方式的缺點(diǎn)是:在執(zhí)行完任務(wù)后無(wú)法獲取執(zhí)行結(jié)果,從JDK5開(kāi)始,就提供了Callable和Future,通過(guò)它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。閱讀過(guò)Android中AsyncTask源碼的同學(xué)應(yīng)該會(huì)發(fā)現(xiàn)AsyncTask中也應(yīng)用了這兩個(gè)類。
7.鎖對(duì)象Lock
用sychronized修飾的方法或者語(yǔ)句塊在代碼執(zhí)行完之后鎖自動(dòng)釋放,而用Lock需要我們手動(dòng)釋放鎖,所以為了保證鎖最終被釋放(發(fā)生異常情況),要把互斥區(qū)放在try內(nèi),釋放鎖放在finally內(nèi)。與synchronized的區(qū)別
8.Condition
Condition中await()對(duì)應(yīng)Object#wait(),signal()對(duì)應(yīng)Object#notify(),signalAll()對(duì)應(yīng)Object#notifyAll(),Condition與Lock結(jié)合使用,通過(guò)Lock.newCondition()方法創(chuàng)建與Lock綁定的Condition實(shí)例。Lock和Condition的關(guān)系就如同 Object.wait(),Object.notify()方法和synchronized一樣,它們都可以配合使用完成對(duì)多線程協(xié)作的控制。
其他不常用的暫不記載,例如CAS、并行計(jì)算的框架Fork/Join、ThreadLocal、BlockingQueue等
技術(shù)有限,錯(cuò)誤的地方還忘大家指出