1. 程式人生 > >執行緒 Thread類

執行緒 Thread類

程序與執行緒

        程序是指一個記憶體中執行的應用程式,每個程序都有自己獨立的一塊記憶體空間,即程序空間或(虛空間)。程序不依賴於執行緒而獨立存在,一個程序中可以啟動多個執行緒。比如在Windows系統中,一個執行的exe就是一個程序。

        執行緒是指程序中的一個執行流程,一個程序中可以執行多個執行緒。比如java.exe程序中可以執行很多執行緒。執行緒總是屬於某個程序,執行緒沒有自己的虛擬地址空間與程序內的其他執行緒一起共享分配給該程序的所有資源

        “同時”執行是人的感覺,線上程之間實際上輪換執行。

        程序在執行過程中擁有獨立的記憶體單元,程序有獨立的地址空間,而多個執行緒共享記憶體,從而極大地提高了程式的執行效率。

        執行緒在執行過程中與程序還是有區別的。每個獨立的執行緒有一個程式執行的入口、順序執行序列和程式的出口。但是執行緒不能夠獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制。

 程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位。

        執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位。執行緒自己基本上不擁有系統資源,只擁有一點在執行中必不可少的資源(如程式計數器,一組暫存器和棧),但是它可與同屬一個程序的其他的執行緒共享程序所擁有的全部資源。

        執行緒有自己的堆疊和區域性變數,但執行緒之間沒有單獨的地址空間,一個執行緒包含以下內容:

 

  •  一個指向當前被執行指令的指令指標;
  • 一個棧;
  • 一個暫存器值的集合,定義了一部分描述正在執行執行緒的處理器狀態的值
  • 一個私有的資料區。

///////////       

        我們使用Join()方法掛起當前執行緒,直到呼叫Join()方法的執行緒執行完畢。該方法還存在包含引數的過載版本,其中的引數用於指定等待執行緒結束的最長時間(即超時)所花費的毫秒數。如果執行緒中的工作在規定的超時時段內結束,該版本的Join()方法將返回一個布林量True。

join方法:

java中Thread類提供join()方法。

作用:用於在當前執行緒A中新增別的執行緒B,這時執行緒A被阻塞,處於Blocked狀態,執行緒B開始執行,當執行緒B執行完以後,執行緒A處於可執行狀(Runnable),等待cpu的排程再執行。

用法:當前執行緒A必須先用myThread的start()啟動執行緒(否則join()不會被執行),然後呼叫join():
//執行緒A中的程式碼
myThread.start();
myThread.join();
//執行緒A中的程式碼

        簡而言之:

  • 一個程式至少有一個程序,一個程序至少有一個執行緒。
  • 執行緒的劃分尺度小於程序,使得多程序程式的併發性高。
  • 另外,程序在執行過程中擁有獨立的記憶體單元,而多個執行緒共享記憶體,從而極大地提高了程式的執行效率。
  • 執行緒在執行過程中與程序還是有區別的。每個獨立的執行緒有一個程式執行的入口、順序執行序列和程式的出口。但是執行緒不能夠獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制。
  • 從邏輯角度來看,多執行緒的意義在於一個應用程式中,有多個執行部分可以同時執行。但作業系統並沒有將多個執行緒看做多個獨立的應用,來實現程序的排程和管理以及資源分配。這就是程序和執行緒的重要區別。

 

Java中的執行緒

 

        在Java中,“執行緒”指兩件不同的事情:

        1、java.lang.Thread類的一個例項;

        2、執行緒的執行。

        在 Java程式中,有兩種方法建立執行緒:

        一是對 Thread 類進行派生並覆蓋 run方法;

        二是通過實現Runnable介面建立。

        使用java.lang.Thread類或者java.lang.Runnable介面編寫程式碼來定義、例項化和啟動新執行緒。

        一個Thread類例項只是一個物件,像Java中的任何其他物件一樣,具有變數和方法,生死於堆上。

        Java中,每個執行緒都有一個呼叫棧,即使不在程式中建立任何新的執行緒,執行緒也在後臺執行著。

        一個Java應用總是從main()方法開始執行,main()方法執行在一個執行緒內,他被稱為主執行緒

        一旦建立一個新的執行緒,就產生一個新的呼叫棧。

        執行緒總體分兩類:使用者執行緒和守候執行緒。

        當所有使用者執行緒執行完畢的時候,JVM自動關閉。但是守候執行緒卻不獨立於JVM,守候執行緒一般是由作業系統或者使用者自己建立的。

 

        在Java中,每次程式執行至少啟動2個執行緒:一個是main執行緒,一個是垃圾收集執行緒。因為每當使用java命令執行一個類的時候,實際上都會啟動一個JVM,每一個JVM實際上就是在作業系統中啟動了一個程序。

      

Thread類:

1.start方法

  start()用來啟動一個執行緒,當呼叫start方法後,系統才會開啟一個新的執行緒來執行使用者定義的子任務,在這個過程中,會為相應的執行緒分配需要的資源。

2.run方法

 run()方法是不需要使用者來呼叫的,當通過start方法啟動一個執行緒之後,當執行緒獲得了CPU執行時間,便進入run方法體去執行具體的任務。

注意,繼承Thread類必須重寫run方法,在run方法中定義具體要執行的任務

補充:用start()方法來啟動執行緒,是真正實現了多執行緒,通過呼叫Thread類的start()方法來啟動一個執行緒,這時此執行緒處於就緒(可執行)狀態,並沒有執行,一旦得到cpu時間片,就開始執行run()方法,無需等待run方法執行完畢,即可繼續執行下面的程式碼。

所以說:

start()方法是真正實現了多執行緒run()方法只是一個普通的方法。

cpu時間片:

時間片即CPU分配給各個程式的時間,每個執行緒被分配一個時間段,稱作它的時間片,即該程序允許執行的時間,使各個程式從表面上看是同時進行的。如果在時間片結束時程序還在執行,則CPU將被剝奪並分配給另一個程序。如果程序在時間片結束前阻塞或結束,則CPU當即進行切換。而不會造成CPU資源浪費

3 sleep方法

  sleep方法有兩個過載版本:

1

2

3

sleep(long millis)     //引數為毫秒

 

sleep(long millis,int nanoseconds)    //第一引數為毫秒,第二個引數為納秒

  
  sleep相當於讓執行緒睡眠,交出CPU,讓CPU去執行其他的任務

但是有一點要非常注意,sleep方法不會釋放鎖,也就是說如果當前執行緒持有對某個物件的鎖,則即使呼叫sleep方法,其他執行緒也無法訪問這個物件

 

鎖: