多線程學習(上)

一、基本概念:程序、進程、線程

程序

  • 完成特定任務、用某種語言編寫的一組指令的集合。一段靜態的代碼,靜態對象。

進程

  • 程序的一次執行過程,或是正在運行的一個程序,動態的過程:產生、存在、和消亡
  • 程序是靜態的,進程是動態的
  • 進程是資源分配的單位

線程

  • 線程是程序內部的一條執行路徑java

  • 一個進程,同一時間並行多個線程,多線程安全

  • 線程做爲調度和執行的單位,每一個線程擁有獨立的運行棧和程序計數器網絡

  • 存在安全問題多線程

  • 一個java應用程序,至少有三個線程:main()主線程,併發

使用多線程的優勢

  1. 提升應用程序的響應,加強用戶體驗
  2. 提升計算機系統CPU的利用率
  3. 改善程序結構,將複雜的進程分爲多個線程,獨立運行

什麼時候須要多線程

  • 程序須要同時執行兩個或多個任務
  • 程序實現一些須要等待的任務時,如:用戶輸入,文件讀寫操做、網絡操做
  • 須要後臺運行的程序

單核CPU和多核CPU

單核CPU

  • 假的多線程,在一個時間單元內,只能執行一個線程的任務
  • 其實是單線程,運行中將其餘進程掛起,執行,執行速度很快,因此在使用上感受是多線程。

多核CPU

  • 真正意義上的多線程

並行與併發

  • 並行:多個CPU同時執行多個任務
  • 併發:一個CPU 「同時」 執行多個任務,如:秒殺

二、線程的建立和使用

線程的建立

  • 方式一ide

    • 繼承於Thread類線程

      步驟:code

      1. 建立一個繼承於Thread的子類
      2. 重寫Thread類的run()方法--》此線程執行的操做
      3. 建立Thread類的子類對象(可以使用匿名對象)
      4. 經過此對象調用start()
      5. 若要再建立新的線程,需建立新的實例來調用start()方法
      //例:遍歷100之內的全部偶數
          //1.建立一個繼承於Thread類的子類
      public class MyThread extends Thread{
          //2.重寫Thread類的run()
          @Override
          public void run() {
              for (int i = 0; i <=1000 ; i++) {
                  if(i%2==0){
                      System.out.println(Thread.currentThread().getName()+":"+i);
                  }
              }
          }
      }
      class ThreadTest {
          public static void main(String[] args) {
              //3.建立Thread類的子類的對象
             MyThread myThread= new MyThread();
             //4.經過此對象調用start()①啓動當前線程②調用當前線程的run()
             myThread.start();
              //  以下操做任然是在main()線程執行的
              for (int i = 0; i <=1000 ; i++) {
                  if(i%2!=0){
      //                Thread.currentThread().getName()獲取線程名
                      System.out.println(Thread.currentThread().getName()+":"+i);
                  }
              }
          }
      }
  • 方式二對象

    • 實現Runnable接口blog

      步驟:

      1. 建立一個實現了Runnable接口的類

      2. 實現類中實現Runnable中的抽象方法:run()

      3. 建立實現類的對象

      4. 將此對象做爲參數傳遞到Thread類的構造器中,建立Thread類的對象

      5. 經過Thread類的對象調用start()

        //1. 建立一個實現了Runnable接口的類
         class MIThread implements Runnable{
        //     2. 實現類中實現Runnable中的抽象方法:run()
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    if(i%2==0){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
        }
        class ThreadTes{
            public static void main(String[] args) {
        //        3. 建立實現類的對象
              MIThread mi=  new MIThread() ;
        //        4. 將此對象做爲參數傳遞到Thread類的構造器中,建立Thread類的對象
              Thread t1=new Thread(mi);
        //        5. 經過Thread類的對象調用start(),啓動當前線程,調用當前線程的run方法,底層是Thread含有Runnable類型參數的構造器
              t1.start();
        //      再啓動一個線程
                Thread t2=new Thread(mi);
                t2.start();
            }
        }
  • 比較兩種建立方式

    • 開發中優先選擇,實現Runnable接口的方式

    • 緣由:

      1. 實現的方式沒有類的單繼承的侷限
      2. 實現方式更適合處理多線程有共享數據的狀況
    • 聯繫: public class Thread implements Runnable

      相同點:兩種方式都須要重寫run() 將線程 要執行的邏輯聲明在run()中;

線程的調度

  • 調度策略
    • 時間片
    • 搶佔式,高優先級的線程搶佔CPU
  • java的調度方法
    • 先來先服務,先進先出隊列
    • 高優先級,優先調度的搶佔式策略

線程優先級

  • 優先級

    • MAX_PRIORITY : 10
    • MIN_PRIORITY: 1
  • NORM_PRIORITY : 5

  • 獲取和設置當前線程的優先級

    • getPriority()
    • setPriority( int p)
  • 高優先級的線程要搶佔低優先級線程的CPU執行權,只是從機率上講,高優先級有很高几率會執行,但並不意味着高優先級的線程執行完,低優先級的才執行;

三、線程的生命週期

線程生命週期的五種狀態

  • 新建:Thread類或子類對象被聲明建立時

  • 就緒:新建的線程被start()後,獲取了其餘全部的資源,只是沒分配到CPU資源

  • 運行:獲取CPU資源,執行

  • 阻塞:某種特殊狀況下,讓出CPU並臨時終止本身的執行

  • 死亡:完成它的所有工做或線程提早被強制性的終止,異常致使結束;

  • 狀態圖

相關文章
相關標籤/搜索