好程式設計師大資料學習路線分享大資料之執行緒

好程式設計師IT發表於2019-09-25

  好程式設計師大資料學習路線分享大資料之執行緒, 預設情況下, 主執行緒和垃圾回收執行緒都是由系統建立的 , 但是我們需要完成自己的功能 ---- 建立自己的執行緒物件

 

 java 將執行緒物件導向了 , 形成的類就是 Thread, Thread 類內部執行任務的方法叫 run()

  注意: 如果想讓 run 作為任務區 , 必須讓他去被自動呼叫 . 我們透過執行 start() 方法 , 來開啟執行緒 , 繼而實現 run 方法的自動呼叫 .

主執行緒的名字:main    子執行緒的名字 : Thread-0 開始命名

 

// 建立自己的執行緒物件

// 分析 : 由於我們實現的實際功能 Thread 類是決定不了的 , 所以沒有辦法將我們的功能放入 Thread run 方法裡,如果我們想實現自己的功能 , 可以寫 Thread 類的子類 , 重寫 run 方法 , 實現我們的功能 .run 就是我們的任務區

 

實現多執行緒的方式兩種:

  第一種方式: 透過建立 Thread 子類的方式實現功能 ---- 執行緒與任務繫結在了一起 , 操作不方便

  第二種: 將任務從執行緒中分離出來 , 哪個執行緒需要工作 , 就將任務交給誰 , 操作方便

當執行緒與任務分離後

這裡Thread 內部預設有一個 run, 又透過 ticket 傳入一個 run, 為什麼優先呼叫的是傳入的 run

如果該執行緒是使用獨立的 Runnable  執行物件構造的,則呼叫該  Runnable  物件的  run  方法;否則,該方法不執行任何操作並返回。

 

2. 執行緒安全

1 synchronized 關鍵字

1 synchronized 關鍵字的作用域有二種:

1 )是某個物件例項內, synchronized aMethod(){} 可以防止多個執行緒同時訪問這個物件的 synchronized 方法(如果一個物件有多個 synchronized 方法,只要一個執行緒訪問了其中的一個 synchronized 方法,其它執行緒不能同時訪問這個物件中任何一個 synchronized 方法)。這時,不同的物件例項的 synchronized 方法是不相干擾的。也就是說,其它執行緒照樣可以同時訪問相同類的另一個物件例項中的 synchronized 方法;

2 )是某個類的範圍, synchronized static aStaticMethod{} 防止多個執行緒同時訪問這個類中的 synchronized static  方法。它可以對類的所有物件例項起作用。

2 、除了方法前用 synchronized 關鍵字, synchronized 關鍵字還可以用於方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。用法是 : synchronized(this){/ 區塊 /} ,它的作用域是當前物件;

3 synchronized 關鍵字是不能繼承的,也就是說,基類的方法 synchronized f(){}  在繼承類中並不自動是 synchronized f(){} ,而是變成了 f(){} 。繼承類需要你顯式的指定它的某個方法為 synchronized 方法;

 

 

實現執行緒安全的方式:

1. 在程式碼中使用同步程式碼塊兒 ( 同步鎖 )

解釋: 在某一段任務中 , 同一時間只允許一個執行緒執行任務 , 其他的執行緒即使搶到了 cpu, 也無法進入當前的任務區間 , 只有噹噹前的執行緒將任務執行完後 , 其他的執行緒才能有資格進入

同步程式碼塊兒的構成:

synchronized( ( 物件 )){

   同步的程式碼

 }

對作為鎖的物件的要求:

1. 必須是物件      

2. 必須保證被多個執行緒共享

可以充當鎖的:

1. 一個普通的物件      

2. 當前物件的引用 --this    

3. 類的位元組碼檔案  -- 注意 : 位元組碼檔案的使用範圍太大 , 一般不建議使用 .

同步程式碼塊兒的特點:

1. 可以保證執行緒的安全    

2. 由於每次都要進行判斷處理 , 所以降低了執行效率

總結: 什麼時候使用同步程式碼塊兒

1. 多個執行緒共享一個資料

2. 至少有兩個執行緒

 

比較同步程式碼塊兒和同步函式

同步程式碼塊兒使用更加的靈活, 只給需要同步的部分程式碼同步即可 , 而同步函式是給這個函式內的所有程式碼同步 .

由於處於同步的程式碼越少越好, 所以最好使用同步程式碼塊兒

注意:1. 當在一個類中同時存在多個 synchronized 修飾的程式碼塊兒或函式時,要想安全,就必須讓他們後面的物件一致。因為只有同一把鎖才能安全。

同步函式的鎖:this

2 靜態同步函式在進記憶體的時候不會建立物件,但是存在其所屬類的位元組碼檔案物件,屬於 class 型別的物件,

所以靜態同步函式的鎖是其所屬類的位元組碼檔案物件

 

示例:

    //使用同步程式碼塊兒

    public void addMoney(int money) {

        synchronized (Bank.class) {

            this.money += money;

            System.out.println(this.money);

        }

    }

    //使用同步函式

    //非靜態的同步函式

    //在synchronized後面預設有一個this

    public synchronized void addMoney(int money) {

        this.money += money;

        System.out.println(this.money);

    }

 

 wait(): 讓當前的執行緒變成等待的狀態 , 放入一個池子 ( 執行緒容器 ), 失去了搶 cpu 的能力 ,. 等待喚醒 ( 鎖相當於給當前的執行緒做了一個標記 )

notify(): 讓當前的執行緒從等待狀態喚醒 , 相當於從池子中取出執行緒 .( 喚醒的是同一把鎖下的任意一個執行緒 )

notifyAll(): 喚醒的是同一把鎖下的所有執行緒

 

死鎖: 出現的情況有兩種

 1. 所有的執行緒處於等待狀態

 2. 鎖之間進行巢狀呼叫

 

2.Lock

比較synchronized Lock

 1.synchronized: jdk1.0 就開始使用的同步方法 - 稱為隱式同步

 synchronized( 鎖物件 ){// 獲取鎖      我們將鎖還可以稱為鎖旗艦或者監聽器

  同步的程式碼

 }// 釋放鎖

 2.Lock: jdk1.5 開始使用的同步方法 - 稱為顯示同步

  原理:Lock 本身是介面 , 要透過他的子類建立物件幹活兒

  使用過程:

  首先呼叫lock() 方法獲取鎖

  進行同步的程式碼塊兒

  使用unlock() 方法釋放鎖

  使用的場景:

  當進行多生產者多消費者的功能時, 使用 Lock, 其他的都使用 synchronized

  使用效率上:Lock 高於 synchronized

 

執行緒的停止: 3

 1. 透過一個標識結束執行緒

 2. 呼叫 stop 方法 --- 因為有固有的安全問題 , 所以系統不建議使用 .

 3. 呼叫 interrupt 方法 ---- 如果目標執行緒等待很長時間(例如基於一個條件變數),則應使用  interrupt  方法來中斷該等待。

 

守護執行緒:

相當於後臺執行緒. 依賴於前臺執行緒 . 正常情況下 , 當前臺執行緒結束的時候 , 不管守護執行緒有沒有結束 , 都會立刻結束 .

  典型的守護執行緒: 垃圾回收執行緒

  當程式呼叫setDaemon 方法時 , 並且將引數設定成 true. 當前執行緒就變成了守護線層 .

  注意: 這個方法一定要在 start 方法之前呼叫

 thread0.setDaemon(true);

 thread0.start();

 

join() 方法 :

 

  原理: 執行緒一旦呼叫了 join 方法 , 他的優先順序會高於主執行緒 . 主執行緒會等當前的執行緒執行完後再去執行 .

  注意點: 優先順序只比 main 執行緒的高 . 對其他的執行緒沒有影響 .

  當執行緒開始工作後, t0 呼叫 join 方法 , 讓他的優先順序高於 main 執行緒

  注意:join 方法必須線上程開始工作後 , 執行 .

     t0.start();
      try {
          t0.join();
      } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

wait(): 使一個執行緒處於等待狀態,並且釋放所持有的物件的 lock

sleep(): 使一個正在執行的執行緒處於睡眠狀態,是一個靜態方法,呼叫此方法要捕捉 InterruptedException 異常。

notify(): 喚醒一個處於等待狀態的執行緒,注意的是在呼叫此方法的時候,並不能確切的喚醒某一個等待狀態的執行緒,而是由 JVM 確定喚醒哪個執行緒,而且不是按優先順序。

notityAll(): 喚醒所有處入等待狀態的執行緒,注意並不是給所有喚醒執行緒一個物件的鎖,而是讓它們競爭

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2658230/,如需轉載,請註明出處,否則將追究法律責任。

相關文章