java
因爲這部分比較基礎,這裏不過多贅述,主要以代碼呈現git
public class MyThread extends Thread {
public void run() {
...
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); //啓動新進程,調用run()
...
}
}
public interface Runnable {
public abstract void run();
}
public class MyRunnable implements Runnable {
public void run() {
...
}
}
public class Main{
public static void main(String[] args) {
/*
*different to Thread
*建立MyRunnable的實例,再以該實例爲參數建立Thread類的實例
*/
new Thread(new MyRunnable()).start();
...
}
}
java.util.concurrent包中包含抽象化ThreadFactory接口github
ThreadFactory factory = Executors.defaultThreadFactory();
//經過Executors.defaultThreadFactor獲取ThreadFactory
factory.newThread(new myRunnable()).start()
具體更加細節的使用會在後面內容中提到,在這裏只是作一個簡單的羅列和歸納,有一些我本身學習過程當中總結的小提醒。express
線程睡眠 Thread.sleep(long millis) 轉到阻塞狀態設計模式
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
sleep 方法使當前運行中的線程睡眼一段時間,進入不可運行狀態,且sleep 方法容許較低優先級的線程得到運行機會。安全
yield 方法使當前線程讓出 CPU 佔有權,但讓出的時間是不可設定的。實際上,yield()方法對應了以下操做:先檢測當前是否有相同優先級的線程處於同可運行狀態,若有,則把 CPU 的佔有權交給此線程,不然,繼續運行原來的線程。因此yield()方法稱爲「退讓」,它把運行機會讓給了同等優先級的其餘線程。另外,yield() 方法執行時,當前線程仍處在可運行狀態,因此,不可能讓出較低優先級的線程些時得到 CPU 佔有權。markdown
中斷本線程多線程
**本線程中斷本身是被容許的,其它線程調用本線程的interrupt()方法時,會經過checkAccess()檢查權限。這有可能拋出SecurityException異常。ide
**若是本線程是處於阻塞狀態:調用線程的wait(), wait(long)或wait(long, int)會讓它進入等待(阻塞)狀態,或者調用線程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會讓它進入阻塞狀態。性能
**若線程在阻塞狀態時,調用了它的interrupt()方法,那麼它的「中斷狀態」會被清除而且會收到一個InterruptedException異常。例如,線程經過wait()進入阻塞狀態,此時經過interrupt()中斷該線程;調用interrupt()會當即將線程的中斷標記設爲「true」,可是因爲線程處於阻塞狀態,因此該「中斷標記」會當即被清除爲「false」,同時,會產生一個InterruptedException的異常。若是線程被阻塞在一個Selector選擇器中,那麼經過interrupt()中斷它時;線程的中斷標記會被設置爲true,而且它會當即從選擇操做中返回。
**若是不屬於前面所說的狀況,那麼經過interrupt()中斷線程時,它的中斷標記會被設置爲「true」。 中斷一個「已終止的線程」不會產生任何操做。
!!!!interrupt()並不會終止處於「運行狀態」的線程!它會將線程的中斷標記設爲true。
synchronized void method() {
...
}
// is equal to
void method() {
synchronized(this) {
... //synchronized靜態方法和動態方法在此例上有所區別,具體請本身查閱資料
}
}
聲明一個方法,表明這個方法只能由一個線程運行
一個實例中的synchronized方法每次只能由一個線程運行,而非synchronized則能夠由兩個以上線程運行。
一個線程運行一個synchronized方法,則該進程得到了鎖,其餘進程就沒法運行該方法,當該方法完成了,便會釋放鎖,一個一直等待鎖的進程便會得到該鎖,開始運行synchronized方法。
而非synchronized方法徹底不受鎖的影響,能夠自由進入。
注意:每一個實例都擁有一個獨立的鎖
synchronized(expression) {
...
}
全部實例都擁有一個等待隊列,它是在wait方法執行後中止操做的線程的隊列
當由其餘線程的notify()或notifyAll()方法喚醒,或有其餘線程的interrupt()方法喚醒,或wait方法超時時,退出等待隊列。
讓線程進入等待隊列
obj.wait();
若要執行wait方法,進程必須持有鎖
從等待隊列中取出一個線程(隨機的)
線程必須持有要調用的實例的鎖
從等待隊列中取出全部線程
wait、notify、notifyAll是Object類的方法,也是Thread類的方法
等待線程終止
guarantee that only one thread can enter a given critical section of code
guarantee that all variables accessed inside the synchronized block will be read in from main memory and when the thread exits the synchronized block,all updated variables will be flushed back to main memory
A得到鎖-->A wait()-->A進入等待隊列,釋放鎖-->B得到鎖-->B notify()-->A退出等待隊列,B仍然持有鎖-->B釋放鎖-->A得到鎖,正式開始執行
在Single Threaded Execution模式中使用到了SharedResource做用的類
SharedResource可被多個線程訪問,主要分爲safeMethod和unsafeMethod,該模式就是爲了保護unsafeMethod,使其同時只能由一個線程訪問。
單線程顯然不必使用,而且調用synchronized方法比通常方法花費時間更多,會下降程序性能。
引用《圖解Java多線程設計模式》中一個不太恰當的例子:在單線程程序中使用synchronized比如一個獨居在家的人上廁所關門同樣。
例如,Immutable模式就徹底不必使用
java的集合類大多非線程安全,請考慮
能夠參考java.util.Collections的API文檔
程序設計性能仍是不得不考慮的一個環節
該模式主要在兩方面會下降程序性能
一個小tips:
java.util.Hashtable和java.util.concurrent.ConcurrentHashMap兩者功能類似,都是線程安全,其中Hashtable採用Single Threaded Execution模式,更易發生線程衝突,ConcurrentHashMap不易。