黑馬程序員-Java基礎-多線程

第一講  多線程概述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)  明確多線程運行代碼中哪些是操做共享數據的;

四、  懶漢式同步問題

懶漢式的實例是延遲加載的,並且存在多條操做語句,在多線程狀況下可能會出現安全問題。此時能夠用同步函數或同步代碼塊來控制,但每次獲取實例時都須要判斷鎖影響效率,咱們能夠經過雙重判斷的方式來減小判斷鎖的次數,從而稍微的提升了運行效率。但實際應用過程當中,建議使用餓漢式。

相關文章
相關標籤/搜索