學習Java的同學注意了!!!
學習進程中遇到甚么問題或想獲得學習資源的話,歡迎加入Java學習交換群,群號碼:183993990 我們1起學Java!
?線程的概述(Introduction)
線程是1個程序的多個履行路徑,履行調度的單位,依托于進程存在。 線程不但可以同享進程的內存,而且還具有1個屬于自己的內存空間,這段內存空間也叫做線程棧,是在建立線程時由系統分配的,主要用來保存線程內部所使用的數據,如線程履行函數中所定義的變量。
注意:Java中的多線程是1種搶占機制而不是分時機制。搶占機制指的是有多個線程處于可運行狀態,但是只允許1個線程在運行,他們通過競爭的方式搶占CPU。
?線程的定義(Defining)
定義1個線程(Defining a Thread)有兩種方法
1) 繼承java.lang.Thread類
/** * 使用繼承java.lang.Thread類的方式創建1個線程 * * @author DreamSea 2011⑴2⑵9 20:17:06 */ public class ThreadTest extends Thread { /** * 重寫(Override)run()方法 JVM會自動調用該方法 */ public void run() { System.out.println("I'm running!"); } }
注意:重寫(override)run()方法在該線程的start()方法被調用后,JVM會自動調用run方法來履行任務;但是重載(overload)run()方法,該方法和普通的成員方法1樣,其實不會因調用該線程的start()方法而被JVM自動運行。 例如:
public class ThreadTest extends Thread { /** * 重寫(Override)run()方法 JVM會自動調用該方法 */ @Override public void run() { System.out.println("I'm running!"); } /** * 重載(Overload)run()方法 和普通的方法1樣,其實不會在該線程的start()方法被調用后被JVM自動運行 */ public void run(int times) { System.out.println("I'm running!(Overload)"); } }
不建議使用此方法定義線程,由于采取繼承Thread的方式定義線程后,你不能在繼承其他的類了,致使程序的可擴大性大大下降。
2) 實現java.lang.Runnable接口
/** * 通過實現Runnable接口創建1個線程 * @author DreamSea */ public class ThreadTest implements Runnable { public void run() { System.out.println("I'm running!"); } }
?線程的啟動(Starting)
任何1個線程的履行的條件都是必須有Thread class的實例存在,并且通過調用run()方法啟動線程。
1)如果線程是繼承Thread類,則創建方式以下:
ThreadTest1 tt = new ThreadTest1();
tt.start();
2)如果是實現Runnable接口,則創建方式以下:
ThreadTest2 tt = new ThreadTest2(); Thread t = new Thread(tt); t.start();
?線程的狀態(State)
新生狀態(New): 當1個線程的實例被創建即便用new關鍵字和Thread類或其子類創建1個線程對象后,此時該線程處于新生(new)狀態,處于新生狀態的線程有自己的內存空間,但該線程并沒有運行,此時線程還不是活著的(not alive);
就緒狀態(Runnable): 通過調用線程實例的start()方法來啟動線程使線程進入就緒狀態(runnable);處于就緒狀態的線程已具有了運行條件,但還沒有被分配到CPU即不1定會被立即履行,此時處于線程就緒隊列,等待系統為其分配CPCU,等待狀態其實不是履行狀態; 此時線程是活著的(alive);
運行狀態(Running): 1旦獲得CPU(被JVM選中),線程就進入運行(running)狀態,線程的run()方法才開始被履行;在運行狀態的線程履行自己的run()方法中的操作,直到調用其他的方法而終止、或等待某種資源而阻塞、或完成任務而死亡;如果在給定的時間片內沒有履行結束,就會被系統給換下來回到線程的等待狀態;此時線程是活著的(alive);
阻塞狀態(Blocked):通過調用join()、sleep()、wait()或資源被暫用使線程處于阻塞(blocked)狀態;處于Blocking狀態的線程依然是活著的(alive)
死亡狀態(Dead):當1個線程的run()方法運行終了或被中斷或被異常退出,該線程到達死亡(dead)狀態。此時可能依然存在1個該Thread的實例對象,當該Thready已不可能在被作為1個可被獨立履行的線程對待了,線程的獨立的call stack已被dissolved。1旦某1線程進入Dead狀態,他就不再能進入1個獨立線程的生命周期了。對1個處于Dead狀態的線程調用start()方法,會出現1個運行期(runtime exception)的異常;處于Dead狀態的線程不是活著的(not alive)。
線程狀態圖
?線程的方法(Method)、屬性(Property)
1)優先級(priority)
每一個類都有自己的優先級,1般property用1⑴0的整數表示,默許優先級是5,優先級最高是10;優先級高的線程其實不1定比優先級低的線程履行的機會高,只是履行的機率高;默許1個線程的優先級和創建他的線程優先級相同;
2)Thread.sleep()/sleep(long millis)
當前線程睡眠/millis的時間(millis指定睡眠時間是其最小的不履行時間,由于sleep(millis)休眠到達后,沒法保證會被JVM立即調度);sleep()是1個靜態方法(static method) ,所以他不會停止其他的線程也處于休眠狀態;線程sleep()時不會失去具有的對象鎖。 作用:保持對象鎖,讓出CPU,調用目的是不讓當前線程獨自霸占該進程所獲得的CPU資源,以留1定的時間給其他線程履行的機會;
3)Thread.yield()
讓出CPU的使用權,給其他線程履行機會、讓同等優先權的線程運行(但其實不保證當前線程會被JVM再次調度、使該線程重新進入Running狀態),如果沒有同等優先權的線程,那末yield()方法將不會起作用。
4)thread.join()
使用該方法的線程會在此之間履行終了后再往下繼續履行。
5)object.wait()
當1個線程履行到wait()方法時,他就進入到1個和該對象相干的等待池(Waiting Pool)中,同時失去了對象的機鎖—暫時的,wait后還要返還對象鎖。當前線程必須具有當前對象的鎖,如果當前線程不是此鎖的具有者,會拋出IllegalMonitorStateException異常,所以wait()必須在synchronized block中調用。
6)object.notify()/notifyAll()
喚醒在當前對象等待池中等待的第1個線程/所有線程。notify()/notifyAll()也必須具有相同對象鎖,否則也會拋出IllegalMonitorStateException異常。
7)Synchronizing Block
Synchronized Block/方法控制對類成員變量的訪問;Java中的每個對象都有唯1的1個內置的鎖,每一個Synchronized Block/方法只有持有調用該方法被鎖定對象的鎖才可以訪問,否則所屬線程阻塞;機鎖具有獨占性、1旦被1個Thread持有,其他的Thread就不能再具有(不能訪問其他同步方法),方法1旦履行,就獨占該鎖,直到從該方法返回時才將鎖釋放,爾后被阻塞的線程方能取得該鎖,重新進入可履行狀態。
學習Java的同學注意了!!!
學習進程中遇到甚么問題或想獲得學習資源的話,歡迎加入Java學習交換群,群號碼:183993990 我們1起學Java!