多執行緒,兩種實現方式(繼承Thread,實現Runnable介面),設定獲取名字,同步程式碼塊、方法,死鎖
阿新 • • 發佈:2019-01-09
1.多執行緒的引入(瞭解)
- 1.什麼是執行緒
- 執行緒是程式執行的一條路徑, 一個程序中可以包含多條執行緒
- 多執行緒併發執行可以提高程式的效率, 可以同時完成多項工作
- 2.多執行緒的應用場景
- 紅蜘蛛同時共享螢幕給多個電腦
- 迅雷開啟多條執行緒一起下載
- QQ同時和多個人一起視訊
- 伺服器同時處理多個客戶端請求
2.多執行緒並行和併發的區別(瞭解)
- 並行就是兩個任務同時執行,就是甲任務進行的同時,乙任務也在進行。(需要多核CPU)
- 併發是指兩個任務都請求執行,而處理器只能按受一個任務,就把這兩個任務安排輪流進行,由於時間間隔較短,使人感覺兩個任務都在執行。
- 比如我跟兩個網友聊天,左手操作一個電腦跟甲聊,同時右手用另一臺電腦跟乙聊天,這就叫並行。
- 如果用一臺電腦我先給甲發個訊息,然後立刻再給乙發訊息,然後再跟甲聊,再跟乙聊。這就叫併發。
3.Java程式執行原理和JVM的啟動是多執行緒的嗎(瞭解)
A:Java程式執行原理
- Java命令會啟動java虛擬機器,啟動JVM,等於啟動了一個應用程式,也就是啟動了一個程序。該程序會自動啟動一個 “主執行緒” ,然後主執行緒去呼叫某個類的 main 方法。
B:JVM的啟動是多執行緒的嗎
- JVM啟動至少啟動了垃圾回收執行緒和主執行緒,所以是多執行緒的。
4.多執行緒程式實現的方式1(掌握)
- 1.繼承Thread
- 定義類繼承Thread
- 重寫run方法
- 把新執行緒要做的事寫在run方法中
- 建立執行緒物件
- 開啟新執行緒, 內部會自動執行run方法
5.多執行緒程式實現的方式2(掌握)
- 2.實現Runnable
- 定義類實現Runnable介面
- 實現run方法
- 把新執行緒要做的事寫在run方法中
- 建立自定義的Runnable的子類物件
- 建立Thread物件, 傳入Runnable
- 呼叫start()開啟新執行緒, 內部會自動呼叫Runnable的run()方法
6.實現Runnable的原理(瞭解)
- 檢視原始碼
- 1,看Thread類的建構函式,傳遞了Runnable介面的引用
- 2,通過init()方法找到傳遞的target給成員變數的target賦值
- 3,檢視run方法,發現run方法中有判斷,如果target不為null就會呼叫Runnable介面子類物件的run方法
7.兩種方式的區別(掌握)
檢視原始碼的區別:
- a.繼承Thread : 由於子類重寫了Thread類的run(), 當呼叫start()時, 直接找子類的run()方法
- b.實現Runnable : 建構函式中傳入了Runnable的引用, 成員變數記住了它, start()呼叫run()方法時內部判斷成員變數Runnable的引用是否為空, 不為空編譯時看的是Runnable的run(),執行時執行的是子類的run()方法
繼承Thread
- 好處是:可以直接使用Thread類中的方法,程式碼簡單
- 弊端是:如果已經有了父類,就不能用這種方法
- 實現Runnable介面
- 好處是:即使自己定義的執行緒類有了父類也沒關係,因為有了父類也可以實現介面,而且介面是可以多實現的
- 弊端是:不能直接使用Thread中的方法需要先獲取到執行緒物件後,才能得到Thread的方法,程式碼複雜
8.匿名內部類實現執行緒的兩種方式
- 繼承Thread類
- 實現Runnable介面
9.多執行緒的方法
(1)獲取名字和設定名字(掌握)
* 1.獲取名字
* 通過getName()方法獲取執行緒物件的名字
* 2.設定名字
* 通過建構函式可以傳入String型別的名字
(2)獲取當前執行緒的物件(掌握)
* Thread.currentThread(), 主執行緒也可以獲取
(3)休眠執行緒(掌握)
* Thread.sleep(毫秒,納秒), 控制當前執行緒休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000納秒 1000000000
(4)守護執行緒(掌握)
* setDaemon(), 設定一個執行緒為守護執行緒, 該執行緒不會單獨執行, 當其他非守護執行緒都執行結束後, 自動退出
(5)加入執行緒(掌握)
* join(), 當前執行緒暫停, 等待指定的執行緒執行結束後, 當前執行緒再繼續
* join(int), 可以等待指定的毫秒之後繼續
(6)禮讓執行緒(瞭解)
* yield讓出cpu
(7)設定執行緒的優先順序(瞭解)
* setPriority()設定執行緒的優先順序
10.同步程式碼塊(掌握)
- 1.什麼情況下需要同步
- 當多執行緒併發, 有多段程式碼同時執行時, 我們希望某一段程式碼執行的過程中CPU不要切換到其他執行緒工作. 這時就需要同步.
- 如果兩段程式碼是同步的, 那麼同一時間只能執行一段, 在一段程式碼沒執行結束之前, 不會執行另外一段程式碼.
2.同步程式碼塊
- 使用synchronized關鍵字加上一個鎖物件來定義一段程式碼, 這就叫同步程式碼塊
多個同步程式碼塊如果使用相同的鎖物件, 那麼他們就是同步的
作用:使多個執行緒在執行某一段程式碼的過程中不讓CPU進行切換。
格式:synchronized(Object obj){語句… } 同步程式碼塊 obj叫作鎖,可以是任意物件
注意:同步程式碼塊中的鎖一定要是同一個物件。
11.同步方法(掌握)
* 使用synchronized關鍵字修飾一個方法, 該方法中所有的程式碼都是同步的
public synchronized void method(){} //鎖是this
public static synchronized void method(){} //鎖是該類的位元組碼物件
12.執行緒安全問題(掌握)
- 多執行緒併發操作同一資料時, 就有可能出現執行緒安全問題
- 使用同步技術可以解決這種問題, 把操作資料的程式碼進行同步, 不要多個執行緒一起操作
一定使用同步程式碼塊把操作這個資料的程式碼進行同步 (注意同步程式碼塊中的鎖必須是同一個鎖)。
13.死鎖(瞭解)
- 多執行緒同步的時候, 如果同步程式碼巢狀, 使用相同鎖, 就有可能出現死鎖
- 儘量不要巢狀使用
14.以前的執行緒安全的類回顧(掌握)
- A:回顧以前說過的執行緒安全問題
- 看原始碼:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx)
- Vector是執行緒安全的,ArrayList是執行緒不安全的
- StringBuffer是執行緒安全的,StringBuilder是執行緒不安全的
- Hashtable是執行緒安全的,HashMap是執行緒不安全的