1. 程式人生 > >多執行緒,兩種實現方式(繼承Thread,實現Runnable介面),設定獲取名字,同步程式碼塊、方法,死鎖

多執行緒,兩種實現方式(繼承Thread,實現Runnable介面),設定獲取名字,同步程式碼塊、方法,死鎖

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是執行緒不安全的