多線程


一、多線程

      1.並發與並行

  • 並發:指兩個或多個事件在同一個時間段內發生。

  • 並行:指兩個或多個事件在同一時刻發生(同時發生)。

     2.線程和進程

  • 進程:是指一個內存中運行的應用程序,每個進程都有一個獨立的內存空間,一個應用程序可以同時運行多個進程;進程也是程序的一次執行過程,是系統運行程序的基本單位;系統運行一個程序即是一個進程從創建、運行到消亡的過程。

  • 線程:線程是進程中的一個執行單元,負責當前進程中程序的執行,一個進程中至少有一個線程。一個進程中是可以有多個線程的,這個應用程序也可以稱之為多線程程序。

     3.1.創建線程一

                       1)定義Thread類的子類(繼承Thread類),並重寫該類的run()方法,該run()方法的方法體就代表了線程需要完成的任務,因此把run()方法稱為線程執行。

                       2)創建Thread子類的實例,即創建了線程對象

                       3)調用線程對象的start()方法來啟動該線程

例:

public class MyThread extends Thread {

//定義指定線程名稱的構造方法
    public MyThread(String name) {
        //調用父類的String參數的構造方法,指定線程的名稱
        super(name);
    }
    /**
     * 重寫run方法,完成該線程執行的邏輯
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(getName()+":正在執行!"+i);
        }
    }
    public static void main(String[] args) {
        //創建自定義線程對象
        MyThread mt = new MyThread("新的線程!");
        //開啟新線程
        mt.start();
        //在主方法中執行for循環
        for (int i = 0; i < 10; i++) {
            System.out.println("main線程!"+i);
        }
    }
}

        3.1.1.Thread類的構造方法

           public Thread() :分配一個新的線程對象。

           public Thread(String name) :分配一個指定名字的新的線程對象。

           public Thread(Runnable target) :分配一個帶有指定目標新的線程對象。

          public Thread(Runnable target,String name) :分配一個帶有指定目標新的線程對象並指定名字

       3.1.2.常用方法

       public String getName() :獲取當前線程名稱。

  public void start() :導致此線程開始執行; Java虛擬機調用此線程的run方法。

  public void run() :此線程要執行的任務在此處定義代碼。

  public static void sleep(long millis) :使當前正在執行的線程以指定的毫秒數暫停(暫時停止執行)。

  public static Thread currentThread() :返回對當前正在執行的線程對象的引用。 

      3.2.創建線程二

          1. 定義Runnable接口的實現類,並重寫該接口的run()方法,該run()方法的方法體同樣是該線程的線程執行體。

   2. 創建Runnable實現類的實例,並以此實例作為Thread的target來創建Thread對象,該Thread對象才是真正 的線程對象。

   3. 調用線程對象的start()方法來啟動線程

例:

             

 

          3.3.Thread和Runnable的區別 

        如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable接口的話,則很容易的實現資源共享;

  實現Runnable接口比繼承Thread類所具有的優勢:

    1. 適合多個相同的程序代碼的線程去共享同一個資源。

    2. 可以避免java中的單繼承的局限性。

    3. 增加程序的健壯性,實現解耦操作,代碼可以被多個線程共享,代碼和線程獨立。

    4. 線程池只能放入實現Runable或Callable類線程,不能直接放入繼承Thread的類。

     4.線程的同步

       4.1.同步代碼塊: synchronized 關鍵字可以用於方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。

          

 

例:

 

 

        同步鎖:

             1. 鎖對象 可以是任意類型。

             2. 多個線程對象 要使用同一把鎖。
           注意:在任何時候,最多允許一個線程擁有同步鎖,誰拿到鎖就進入代碼塊,其他的線程只能在外等着

        4.2.同步方法

  •  同步方法:使用synchronized修飾的方法,就叫做同步方法,保證A線程執行該方法的時候,其他線程只能在方法外 等着。

格式:

 

         同步鎖:

                   對於非static方法,同步鎖就是this。
                   對於static方法,我們使用當前方法所在類的字節碼對象(類名.class)

          4.3.Lock鎖

  • Lock比synchronized代碼塊和synchronized方法更廣泛的鎖定操作, 同步代碼塊/同步方法具有的功能Lock都有,除此之外更強大,更體現面向對象。 

            1) public void lock() :加同步鎖。

            2) public void unlock() :釋放同步鎖

            3)Lock接口的實現類ReentrantLock

例:

         

 

       5.線程狀態

              

 

 二、線程池

       1.等待喚醒機制

  • 等待喚醒機制就是用於解決線程間通信的問題的,使用到的3個方法的含義如下:
  1. wait:線程不再活動,不再參與調度,進入 wait set 中,因此不會浪費 CPU 資源,也不會去競爭鎖了,這時的線程狀態即是 WAITING。它還要等着別的線程執行一個特別的動作,也即是“通知(notify)”在這個對象上等待的線程從wait set 中釋放出來,重新進入到調度隊列(ready queue)中

  2. notify:則選取所通知對象的 wait set 中的一個線程釋放;例如,餐館有空位置后,等候就餐最久的顧客最先入座。

  3. notifyAll:則釋放所通知對象的 wait set 上的全部線程。

  •  調用wait和notify方法需要注意的細節
  1. wait方法與notify方法必須要由同一個鎖對象調用。因為:對應的鎖對象可以通過notify喚醒使用同一個鎖對象調用的wait方法后的線程。

  2. wait方法與notify方法是屬於Object類的方法的。因為:鎖對象可以是任意對象,而任意對象的所屬類都是繼承了Object類的。

  3. wait方法與notify方法必須要在同步代碼塊或者是同步函數中使用。因為:必須要通過鎖對象調用這2個方法。

    2.線程池

 

 線程池優點:   

  1. 降低資源消耗。減少了創建和銷毀線程的次數,每個工作線程都可以被重復利用,可執行多個任務。

  2. 提高響應速度。當任務到達時,任務可以不需要的等到線程創建就能立即執行。

  3. 提高線程的可管理性。可以根據系統的承受能力,調整線程池中工作線線程的數目,防止因為消耗過多的內存,而把服務器累趴下(每個線程需要大約1MB內存,線程開的越多,消耗的內存也就越大,最后死機)。

三、Lambda表達式

          借助Java 8的全新語法,上述Runnable接口的匿名內部類寫法可以通過更簡單的Lambda表達式達到等效:

public class Demo02LambdaRunnable {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("多線程任務執行!")).start(); // 啟動線程
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM