用於表示多個操做「依次處理」。好比把十個操做交給一我的來處理時,這我的要一個一個地按順序來處理java
用於標識多個操做「同時處理」。好比十個操做分給兩我的處理時,這兩我的就會並行來處理。設計模式
相對於順序和並行來講比較抽象,用於表示「將一個操做分割成多個部分而且容許無序處理」。好比將十個操做分紅相對獨立的兩類,這樣便可以開始併發處理了。若是一我的來處理,這我的就是順序處理分開的併發操做,而若是是兩我的,這兩我的就能夠並行處理同一個操做。多線程
多線程程序都是併發處理的。若是 CPU 只有一個,那麼併發處理就是順序執行的,而若是有多個 CPU,那麼併發處理就可能會並行運行。併發
併發處理的順序執行與併發處理的並行執行示意圖以下所示 this
Thread
類的子類的實例啓動線程Runnable
接口的實現類的實例啓動線程以上兩種方式都須要使用 start 方法用於啓動新的線程,在此須要注意的事情是,啓動新線程調用的是 start 方法而不是 run 方法url
直到全部的線程都終止後,程序纔會終止。也就是說,當這兩個線程都終止後,程序纔會終止。spa
Java 程序的終止是指除守護線程之外的線程所有終止。守護線程是執行後臺做業的線程。咱們能夠經過
setDaemon
方法把線程設置爲守護線程。線程
java.util.concurrent 包中包含一個將線程建立抽象化的 ThreadFactory 接口。利用該接口,咱們能夠將 Runnable 做爲傳入參數並經過 new 建立 Thread 實例的處理隱藏在 ThreadFactory 內部。設計
Executors 類中含有多種建立 ThreadFactory 的方法,感興趣的能夠去看一下源碼code
若是聲明一個方法時,在前面加上關鍵字 synchronized 那麼這個方法就只能由一個線程運行。只能由一個線程運行是每次只能由一個線程運行的意思,並非說僅能讓某一特定線程運行。這種方法叫作 synchronized,有時也稱爲同步方法。
synchronized void method() {
...
}
複製代碼
若是隻是想讓方法中的某一部分由一個線程運行,而非整個方法,則可以使用 synchronized 代碼塊
synchronized (表達式) {
...
}
複製代碼
假設有以下 synchronized 實例方法
synchronized void method() {
...
}
複製代碼
這跟下面將方法體用 synchronized 代碼塊包圍起來是等效的
void method() {
synchronized (this) {
...
}
}
複製代碼
synchronized 實例方法是使用 this 的鎖來執行線程的互斥處理的
synchronized 靜態方法和 synchronized 實例方法是相同的。可是 synchronized 靜態方法使用的鎖和 synchronized 實例方法使用的鎖是不同的
class Something {
static synchronized void method() {
...
}
}
複製代碼
這跟下面將方法體用 synchronized 代碼塊包圍起來是等效的
class Something {
static void method() {
synchronized (Something.class) {
...
}
}
}
複製代碼
synchronized 靜態方法是使用該類的類對象鎖來執行線程的互斥處理的。 Something.class 是 Something 類對應的 java.lang.class 類的實例
全部實例都擁有一個等待隊列,它是在實例的 wait 方法執行後中止操做的線程隊列。就比如爲每一個實例準備的線程休息室
在執行 wait 方法後,線程便會暫停操做,進入等待隊列這個休息室。除非發生下列某一狀況,不然線程會一直在等待隊列中休眠。
若要執行 wait 方法,線程必須持有鎖。但若是線程進入等待隊列,便會釋放其實例的鎖
該方法會將等待隊列中的一個線程去除。同 wait 方法同樣,若要執行 notify 方法,線程也必須持有要調用的實例的鎖。
notify 喚醒的線程並不會在執行 notify 的一瞬間就從新運行。由於在執行 notify 的那一瞬間,執行 notify 的線程還持有着鎖,因此其餘線程還沒法獲取這個實例的鎖
notify 方法僅喚醒一個線程,而 notifyAll 則喚醒全部線程,這是二者之間惟一的區別
同 wait 方法和 notify 方法同樣, notifyAll 方法也只能由持有要調用的實例鎖的線程調用
notify 方法和 notifyAll 方法很是類似,到底該使用哪一個?
實際上,這很難選擇,因爲 notify 喚醒的線程較少,因此處理速度要比使用 notifyAll 時快。 但使用 notify 時,若是處理很差,程序即可能會中止。通常來講,使用 notifyAll 時的代碼要比使用 notify 時的更爲健壯。