java進階學習--java多線程

來源:互聯網
上載者:User

標籤:自己   服務   turn   後台運行   center   span   關鍵字   sleep   佔用   

多線程一、多線程  1、進程與線程     

進程:一個電腦程式的運行執行個體,包含了需要執行的指令;有自己的獨立地址空間,包含程式內容和資料;不同進程的地址空間是互相隔離的;

  進程擁有各種資源和狀態資訊,包括開啟的檔案、子進程和訊號處理。

線程:表示程式的執行流程,是CPU調度執行的基本單位;線程有自己的程式計數器、寄存器、堆棧和幀。同一進程中的線程共用相同的地址空間,

   同時共用進程鎖擁有的記憶體和其他資源。

 

2、Java標準庫提供了進程和線程相關的API

    進程主要包括表示進程的java.lang.Process類和建立進程的java.lang.ProcessBuilder類;

    表示線程的是java.lang.Thread類,在虛擬機器啟動之後,通常只有Java類的main方法這個普通線程運行,運行時可以建立和啟動新的線程;

    有一類守護線程(damon thread),守護線程在後台運行,提供者運行時所需的服務。當虛擬機器中啟動並執行所有線程都是守護線程時,虛擬機器終止運行。

       3、線程的生命週期

    線程是一個動態執行的過程,它也有一個從產生到死亡的過程。

    

    • 建立狀態:

      使用 new 關鍵字和 Thread 類或其子類建立一個線程對象後,該線程對象就處於建立狀態。它保持這個狀態直到程式start() 這個線程。

    • 就緒狀態:

      當線程對象調用了start()方法之後,該線程就進入就緒狀態。就緒狀態的線程處於就緒隊列中,要等待JVM裡線程調度器的調度。

    • 運行狀態:

      如果就緒狀態的線程擷取 CPU 資源,就可以執行 run(),此時線程便處於運行狀態。處於運行狀態的線程最為複雜,它可以變為阻塞狀態、就緒狀態和死亡狀態。

    • 阻塞狀態:

      如果一個線程執行了sleep(睡眠)、suspend(掛起)等方法,失去所佔用資源之後,該線程就從運行狀態進入阻塞狀態。在睡眠時間已到或獲得裝置資源後可以重新進入就緒狀態。可以分為三種:

      • 等待阻塞:運行狀態中的線程執行 wait() 方法,使線程進入到等待阻塞狀態。

      • 同步阻塞:線程在擷取 synchronized 同步鎖失敗(因為同步鎖被其他線程佔用)。

      • 其他阻塞:通過調用線程的 sleep() 或 join() 發出了 I/O 請求時,線程就會進入到阻塞狀態。當sleep() 狀態逾時,join() 等待線程終止或逾時,或者 I/O 處理完畢,線程重新轉入就緒狀態。

    • 死亡狀態:

      一個運行狀態的線程完成任務或者其他終止條件發生時,該線程就切換到終止狀態。

  4、線程的優先順序    

每一個 Java 線程都有一個優先順序,這樣有助於作業系統確定線程的調度順序。

Java 線程的優先順序是一個整數,其取值範圍是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。

預設情況下,每一個線程都會分配一個優先順序 NORM_PRIORITY(5)。

具有較高優先順序的線程對程式更重要,並且應該在低優先順序的線程之前分配處理器資源。但是,線程優先順序不能保證線程執行的順序,而且非常依賴於平台。

  5、線程的建立      

  Java 提供了三種建立線程的方法:

      • 通過實現 Runnable 介面;
      • 通過繼承 Thread 類本身;
      • 通過 Callable 和 Future 建立線程。

    1、通過實現 Runnable 介面來建立線程    

 

(1)定義runnable介面的實作類別,並重寫該介面的run()方法,該run()方法的方法體同樣是該線程的線程執行體。

 

(2)建立 Runnable實作類別的執行個體,並依此執行個體作為Thread的target來建立Thread對象,該Thread對象才是真正的線程對象。

 

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

樣本:

 1 package com.thread;   2    3 public class RunnableThreadTest implements Runnable   4 {   5    6     private int i;   7     public void run()   8     {   9         for(i = 0;i <100;i++)  10         {  11             System.out.println(Thread.currentThread().getName()+" "+i);  12         }  13     }  14     public static void main(String[] args)  15     {  16         for(int i = 0;i < 100;i++)  17         {  18             System.out.println(Thread.currentThread().getName()+" "+i);  19             if(i==20)  20             {  21                 RunnableThreadTest rtt = new RunnableThreadTest();  22                 new Thread(rtt,"新線程1").start();  23                 new Thread(rtt,"新線程2").start();  24             }  25         }  26   27     }  28   29 }  
  2、繼承Thread類建立線程類   

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

(2)建立Thread子類的執行個體,即建立了線程對象。

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

 1 package com.thread;   2    3 public class FirstThreadTest extends Thread{   4     int i = 0;   5     //重寫run方法,run方法的方法體就是現場執行體   6     public void run()   7     {   8         for(;i<100;i++){   9         System.out.println(getName()+"  "+i);  10           11         }  12     }  13     public static void main(String[] args)  14     {  15         for(int i = 0;i< 100;i++)  16         {  17             System.out.println(Thread.currentThread().getName()+"  : "+i);  18             if(i==20)  19             {  20                 new FirstThreadTest().start();  21                 new FirstThreadTest().start();  22             }  23         }  24     }  25   26 }  

    上述代碼中Thread.currentThread()方法返回當前正在執行的線程對象。GetName()方法返回調用該方法的線程的名字。

  3、通過Callable和Future建立線程    

(1)建立Callable介面的實作類別,並實現call()方法,該call()方法將作為線程執行體,並且有傳回值。

(2)建立Callable實作類別的執行個體,使用FutureTask類來封裝Callable對象,該FutureTask對象封裝了該Callable對象的call()方法的傳回值。

(3)使用FutureTask對象作為Thread對象的target建立並啟動新線程。

(4)調用FutureTask對象的get()方法來獲得子線程執行結束後的傳回值

樣本: 

 1 package com.thread;   2    3 import java.util.concurrent.Callable;   4 import java.util.concurrent.ExecutionException;   5 import java.util.concurrent.FutureTask;   6    7 public class CallableThreadTest implements Callable<Integer>   8 {   9   10     public static void main(String[] args)  11     {  12         CallableThreadTest ctt = new CallableThreadTest();  13         FutureTask<Integer> ft = new FutureTask<>(ctt);  14         for(int i = 0;i < 100;i++)  15         {  16             System.out.println(Thread.currentThread().getName()+" 的迴圈變數i的值"+i);  17             if(i==20)  18             {  19                 new Thread(ft,"有傳回值的線程").start();  20             }  21         }  22         try  23         {  24             System.out.println("子線程的傳回值:"+ft.get());  25         } catch (InterruptedException e)  26         {  27             e.printStackTrace();  28         } catch (ExecutionException e)  29         {  30             e.printStackTrace();  31         }  32   33     }  34   35     @Override  36     public Integer call() throws Exception  37     {  38         int i = 0;  39         for(;i<100;i++)  40         {  41             System.out.println(Thread.currentThread().getName()+" "+i);  42         }  43         return i;  44     }  45   46 }  
    4、建立線程的三種方式的對比      

採用實現Runnable、Callable介面的方式創見多線程時,

優勢是:

線程類只是實現了Runnable介面或Callable介面,還可以繼承其他類。

在這種方式下,多個線程可以共用同一個target對象,所以非常適合多個相同線程來處理同一份資源的情況,從而可以將CPU、代碼和資料分開,形成清晰的模型,較好地體現了物件導向的思想。

劣勢是:

編程稍微複雜,如果要訪問當前線程,則必須使用Thread.currentThread()方法。

使用繼承Thread類的方式建立多線程時

優勢是:

編寫簡單,如果需要訪問當前線程,則無需使用Thread.currentThread()方法,直接使用this即可獲得當前線程。

劣勢是:

線程類已經繼承了Thread類,所以不能再繼承其他父類。

  5、小結:

      在多線程的使用上:有效利用多線程的關鍵是理解程式是並發執行而不是串列執行的。例如:程式中有兩個子系統需要並發執行,這時候就需要利用多線程編程。

      另外在多線程編程時:

        重點理解:         

        • 線程同步
        • 線程間通訊
        • 線程死結
        • 線程式控制制:掛起、停止和恢複

    

    參考部落格:http://blog.csdn.net/escaflone/article/details/10418651

          http://blog.csdn.net/longshengguoji/article/details/41126119

          http://www.runoob.com/java/java-multithreading.html

          http://www.tiantianbianma.com/java-wait-notify.html/

 

java進階學習--java多線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.