Java基礎之008-多線程
35歲學習Java
1、進程和線程的概念。1) 概念 進程:進行中中的程式(直譯). 線程:就是進程中一個負責程式執行的控制單元(執行路徑) 任務:每一個線程都有自己啟動並執行內容。這個內容可以稱為線程要執行的任務。 提示:一個進程中可以多執行路徑,稱之為多線程。一個進程中至少要有一個線程。2) 建立多線程的目的 開啟多個線程是為了同時運行多部分代碼。3) 多線程的原理 其實應用程式的執行都是cpu在做著快速的切換完成的。這個切換是隨機的。4) 多線程的優劣 多線程好處:解決了多部分同時啟動並執行問題。 多線程弊端:線程太多導致效率的降低。5) JVM啟動時就啟動了多個線程 執行main函數的線程, 該線程的任務代碼都定義在main函數中。 負責記憶體回收的線程。 自訂線程2、建立線程方式一 繼承Thread類 1) 子類覆蓋父類中的run方法,將線程啟動並執行代碼存放在run中。 2) 建立子類對象的同時線程也被建立。 3) 通過調用start方法開啟線程。 線程的四種狀態
3、建立線程方式二1) 實現Runnable介面 子類覆蓋介面中的run方法。2) 通過Thread類建立線程,並將實現了Runnable介面的子類對象作為參數傳遞給Thread類的建構函式。 thread類對象調用start方法開啟線程。3) 思考:為什麼要給Thread類的建構函式傳遞Runnable的子類對象? 因為線程的任務都封裝在Runnable介面子類對象的run方法中。所以要線上程對象建立時就必須明確要啟動並執行任務。4) 實現Runnable介面的好處: A.將線程的任務從線程的子類中分離出來,進行了單獨的封裝。按照物件導向的思想將任務封裝成對象。 B.避免了java單繼承的局限性。
4、安全執行緒問題 導致安全問題出現的原因: 1) 多個線程在操作共用的資料。 2) 操作共用資料的線程代碼有多條。 3) 線程隨機性 。 當一個線程在執行操作共用資料的多條代碼過程中,其他線程參與了運算。就會導致安全執行緒問題的產生。 註:安全執行緒問題在理想狀態下,不容易出現,但一旦出現對軟體的影響是非常大的。
5、同步(synchronized) 解決安全執行緒問題的思路: 就是將多條操作共用資料的線程代碼封裝起來,當有線程在執行這些代碼的時候,其他線程時不可以參與運算的。必須要當前線程把這些代碼都執行完畢後,其他線程才可以參與運算。
格式: synchronized(對象) { 需要同步的代碼; } 同步可以解決安全問題的根本原因就在那個對象上。該對象如同鎖的功能。5.1 同步的前提:1) 同步需要兩個或者兩個以上的線程。2) 多個線程使用的是同一個鎖。 未滿足這兩個條件,不能稱其為同步。5.2 同步的弊端: 當線程相當多時,因為每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程式的運行效率。5.3 同步函數 格式: 在函數上加上synchronized修飾符即可。 思考:同步函數用的是哪個鎖呢?(this)
6、線程間通訊
6.1等待/喚醒機制。1) wait(): 讓線程處於凍結狀態,被wait的線程會被儲存到線程池中。2) notify():喚醒線程池中一個線程(任意).只能喚醒一個線程,如果本方喚醒了本方,沒有意義。而且while判斷標記+notify會導致死結。3) notifyAll():喚醒線程池中的所有線程。解決了本方線程一定會喚醒對方線程的問題。 這些方法都必須定義在同步中。因為這些方法是用於操作線程狀態的方法。6.2新的機制1) jdk1.5以後將同步和鎖封裝成了對象。 並將操作鎖的隱式方式定義到了該對象中,將隱式動作變成了顯示動作。2) Lock介面: 出現替代了同步代碼塊或者同步函數。將同步的隱式鎖操作變成顯式鎖操作。同時更為靈活。可以一個鎖上加上多組監視器。lock():擷取鎖。 unlock():釋放鎖,通常需要定義finally代碼塊中。3) Condition介面:出現替代了Object中的wait, notify,notifyAll方法。將這些監視器方法單獨進行了封裝,變成Condition監視器對象。 可以任意鎖進行組合。 await(); signal(); signalAll();
7、停止線程1) 定義迴圈結束標記因為線程運行代碼一般都是迴圈,只要控制了迴圈即可。2) 使用interrupt(中斷)方法。該方法是結束線程的凍結狀態,使線程回到運行狀態中來。強制動作會引起InterruptedException,記得要處理註:stop方法已經過時不再使用。
8、線程類的其他方法1) setPriority(int num) 設定後可以改變獲得CPU執行權的幾率,優先順序越大,擷取CPU執行權的幾率越高。預設為5(NORM_PRIORITY),最小為1(MIN_PRIORITY),最大為10(MAX_PRIORITY)是靜態常量。2) setDaemon(boolean b) 將該線程設為守護線程(後台線程),當啟動並執行都是守護線程時,虛擬機器退出。該方法必須在啟動線程前調用。3) join() 臨時加入一個線程運算時可以使用join方法。該線程會獲得執行資格和執行權。4) toString() 返回該線程的字串表現形式,包括名稱、優先順序、線程組(線程組可以統一管理組內的線程,如統一interrupt等。)5) yield(); 暫停當前正在執行的線程對象,並執行其他線程。是個靜態方法。