第一講 多線程概述java
一、 定義設計模式
進程:是一個正在執行中的程序。每個進程執行都有一個執行順序,該順序是一個執行路徑,或者叫一個控制單元。在程序運行時,會被分配一個內存空間,進程就用於標識這個空間,封裝單元,線程纔是線程中真正執行的哦部分。安全
線程:就是進程中的一個獨立的控制單元,線程在控制着進程的執行。多線程
一個進程中至少有一個線程。jvm
例子:java JVM 啓動時會有一個進程java.exe。該進程中至少一個線程負責java程序的執行,並且這個線程運行的代碼存在於main方法中,該線程就稱爲主線程。函數
說明:jvm啓動時不止一個線程,還有一個負責垃圾回收機制的線程。this
二、 多線程線程
多線程可使得多個代碼「同步」執行。在單核的前提下,多個線程都在獲取cpu的執行權,cpu執行到誰,誰就運行。須要明確的是,在某一個時刻,只能有一個線程在運行。設計
第二講 建立線程-繼承Tread類3d
一、 建立線程第一種方式:繼承Tread類
步驟:
1)定義類繼承Tread類;
2)複寫Tread類中的run方法;
3)調用線程的start()方法,該方法有兩個做用:啓動線程、調用run方法;
二、 run和start方法特性
Thread類用於描述線程,該類就定義了一個功能,用於存放線程要運行的代碼,該存儲功能就是run方法。主線程把運行的代碼存儲在main方法中。
複寫run方法的目的:將自定義的代碼存儲在run方法中,讓線程運行。
三、 練習:建立兩個線程,和主線程交替運行
l 定義線程類繼承Tread類
l 建立兩個線程;
l 啓動兩個線程;
代碼實現以下:
四、 線程運行狀態
線程在運行過程當中有以下5中狀態:建立、運行、凍結、臨時狀態(阻塞)、消亡。
這幾種狀態之間的關係以下:
五、 線程在虛擬機中的名稱
獲取線程名稱:
獲取線程名稱格式:線程對象.getName();
線程都有本身默認的名稱:Thread-編號,該編號從0開始。
設置線程名稱:
setName()或構造函數設置線程名稱。
Thread類的構造函數和爲線程設置名稱,所以,能夠在定義線程類時,調用Thread類的構造函數來設置線程的名稱。
Thread類中的方法currentThread()能夠獲取到當前運行的線程對象。
獲取和設置線程名稱的意義:當線程多的時候,能夠對線程進行管理。
第三講 建立線程-實現Runnable接口
一、 多個窗口同時賣票例子
建立多個線程,同時執行賣票功能。
利用繼承Thread類方法建立線程,實現多個窗口同時賣票,但票的數量必須定義爲靜態的,不然會出現多賣的狀況。而後咱們在寫代碼時,較少定義靜態變量,由於靜態變量生存週期較長浪費資源。
所以,就引入了第二種建立線程的方式:實現Runnable接口
二、 建立線程的第二種方式——實現Runnable接口
步驟:
1) 定義類實現Runnable接口;
2) 覆蓋Runnable接口中的run方法;
目的:將線程要運行的代碼存放在該run方法中。
3) 經過Thread類創建線程對象;
4) 將Runnable接口的子類對象做爲實際參數傳遞給Thread類的構造函數;
要將Runnable接口的子類對象傳遞給Thread類的構造函數。
由於:自定義的run方法所屬的對象是Runnable接口的子類對象,因此要讓線程去指定指定對象的run方法。即,明確該run方法所屬的對象。
5) 調用Thread類的start方法,並開啓線程,並調用Runnable接口子類的run方法;
代碼實現以下:
實現方式與繼承方式的對比的好處:
l 實現方式能夠避免java單繼承的侷限性,在定義線程時,建議使用實現方式;
l 資源被獨立了出來,解決了多窗口賣票的問題;——這個賣票過程只在內存中建立了一個tick,多個賣票線程只能對這個票資源進行操做。
第四講 多線程安全問題
一、 多線程安全問題概述
問題出現的緣由:當多條語句在操做同一個線程共享數據時,一個線程對多條語句執行了一部分,尚未執行完,就被另外一個線程參與進來執行,致使共享數據的錯誤。
解決辦法:對多條操做共享數據的語句,只能讓一個線程執行完了,才能讓其餘線程參與進來。
Java中的解決辦法:同步代碼塊
Synchronized(對象)
{
須要被同步的代碼
}
說明:對象如同鎖,持有鎖的線程能夠在同步中執行,沒有持有鎖的線程即便獲取cpu的執行權,也進不去,由於沒有獲取鎖。
二、 同步使用
同步使用的前提:必需要有兩個或兩個以上的線程;必須是多個線程使用同一個鎖。
同步的好處:解決了多線程的安全問題;
同步的弊端:多個線程須要判斷鎖,較爲耗費資源;
三、 同步的表現形式
同步代碼塊
代碼示例:
同步函數
四、 同步中的鎖
1) 同步代碼塊的鎖能夠 是任意的對象;
2) 同步代函數的鎖是this(函數所在類的實例對象);
3) 同步靜態函數的鎖是該類對應的字節碼文件對象,類名.class;
第五講 同步在單例設計模式中的應用
一、 概述
單例設計模式有兩種體現方式:餓漢式和懶漢式。
由於懶漢式是函數被調用時纔會建立對象,而建立對象的語句不止一條,因此在多線程時容易出現安全隱患。
二、 解決懶漢式安全問題方法
將獲取對象的函數定義爲同步的,以下:
但每次調用該函數時都須要判斷鎖,影響運行效率,能夠經過雙重判斷形式來稍微提升運行效率,以下。這樣,能夠減小鎖的次數,但代碼增多了。
三、 死鎖
同步中嵌套同步,並且同步的鎖不同。並且不一樣線程都在等待對方的鎖。
知識點總結
一、 建立線程有兩種方式:繼承Thread類;實現Runnable接口
實現Runnable接口能夠解決多結成問題,還能將資源獨立出來,保證資源的惟一性。
二、 多線程的出現使得不少程序能夠「同時」運行,但可能會出現共享數據錯誤,形成多線程安全問題,此時,能夠經過同步機制來進行控制,同步包括:同步代碼塊、同步函數。
三、 使用同步代碼塊時,須要明確以下問題:
1) 明確哪些代碼是多線程運行代碼(run方法中的代碼);
2) 明確共享數據;
3) 明確多線程運行代碼中哪些是操做共享數據的;
四、 懶漢式同步問題
懶漢式的實例是延遲加載的,並且存在多條操做語句,在多線程狀況下可能會出現安全問題。此時能夠用同步函數或同步代碼塊來控制,但每次獲取實例時都須要判斷鎖影響效率,咱們能夠經過雙重判斷的方式來減小判斷鎖的次數,從而稍微的提升了運行效率。但實際應用過程當中,建議使用餓漢式。