JAVA多線程

1 Thread類和Runable方法

a)繼承Thread

JavaThread類對線程進行封裝,一旦創建了這個Thread實例,jvm就會爲我們創建一個線程,當我們調用Thread類的strat方法時,線程就開始運行起來

(b)實現Runble接口

Runblejava提供的一個線程相關的接口,接口定義了一個方法

2兩種線程實現方法的比較

不論是那種方式,最後都需要通過Thread類的實例調用start()方法來開始線程的執行,start()方法通過java虛擬機調用線程中定義的run方法來執行該線程。通過查看java源程序中的start()方法的定義可以看到,它是通過調用操作系統的start0方法來實現多線程的操作的。

但是一般在系統的開發中遇到多線程的情況的時候,以實現Runnable接口的方式爲主要方式。這是因爲實現接口的方式有很多的優點:

1、就是通過繼承Thread類的方式時,線程類就無法繼承其他的類來實現其他一些功能,實現接口的方式就沒有這中限制;

2.也是最重要的一點就是,通過實現Runnable接口的方式可以達到資源共享的效果

3 線程的狀態和屬性

1. 新建狀態(New):新創建了一個線程對象。
2. 
就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3. 
運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
4. 
阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:
(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
(三)、其他阻塞:運行的線程執行sleep()join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

5. 死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

4 阻止線程執行

對於線程的阻止,考慮一下三個方面,不考慮IO阻塞的情況:

睡眠;

等待;

因爲需要一個對象的鎖定而被阻塞

@a 睡眠 Thread.sleep(long millis)Thread.sleep(long millis, int nanos)靜態方法強制當前正在執行的線程休眠(暫停執行),以減慢線程。當線程睡眠時,它入睡在某個地方,在甦醒之前不會返回到可運行狀態。當睡眠時間到期,則返回到可運行狀態。

注意:

1、線程睡眠是幫助所有線程獲得運行機會的最好方法。

2、線程睡眠到期自動甦醒,並返回到可運行狀態,不是運行狀態。sleep()中指定的時間是線程不會運行的最短時間。因此,sleep()方法不能保證該線程睡眠到期後就開始執行。

3sleep()是靜態方法,只能控制當前正在運行的線程。

@b 線程的優先級和線程讓步yield()

Thread.yield()方法作用是:暫停當前正在執行的線程對象,並執行其他線程。

yield()應該做的是讓當前運行線程回到可運行狀態,以允許具有相同優先級的其他線程獲得運行機會。因此,使用yield()的目的是讓相同優先級的線程之間能適當的輪轉執行。但是,實際中無法保證yield()達到讓步目的,因爲讓步的線程還有可能被線程調度程序再次選中。

結論:yield()從未導致線程轉到等待/睡眠/阻塞狀態。在大多數情況下,yield()將導致線程從運行狀態轉到可運行狀態,但有可能沒有效果。

@c join()方法

Thread的非靜態方法join()讓一個線程B“加入到另外一個線程A的尾部。在A執行完畢之前,B不能工作。例如:

        Thread t = new MyThread();
        t.start();
        t.join();

另外,join()方法還有帶超時限制的重載版本。例如t.join(5000);則讓線程等待5000毫秒,如果超過這個時間,則停止等待,變爲可運行狀態

5 離開運行狀態方法總結

到目前位置,介紹了線程離開運行狀態的3種方法:

1、調用Thread.sleep():使當前線程睡眠至少多少毫秒(儘管它可能在指定的時間之前被中斷)。

2、調用Thread.yield():不能保障太多事情,儘管通常它會讓當前運行線程回到可運行性狀態,使得有相同優先級的線程有機會執行。

3、調用join()方法:保證當前線程停止執行,直到該線程所加入的線程完成爲止。然而,如果它加入的線程沒有存活,則當前線程不需要停止。

 

除了以上三種方式外,還有下面幾種特殊情況可能使線程離開運行狀態:

1、線程的run()方法完成。

2、在對象上調用wait()方法(不是在線程上調用)。

3、線程不能在對象上獲得鎖定,它正試圖運行該對象的方法代碼。

4、線程調度程序可以決定將當前運行狀態移動到可運行狀態,以便讓另一個線程獲得運行機會,而不需要任何理由。

6 java線程:同步與鎖   synchronized

7 線程間通信(線程交互)

    SCJP所要求的線程交互知識點需要從java.lang.Object的類的三個方法來學習:

  void notify() 
          
喚醒在此對象監視器上等待的單個線程。
 void notifyAll() 
          
喚醒在此對象監視器上等待的所有線程。
 void wait() 
          
導致當前的線程等待,直到其他線程調用此對象的 notify()方法或 notifyAll()方法。


 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章