天天看點

多線程常用方法 sleep wait join等以及對鎖的控制

1.sleep() 

    使目前線程(即調用該方法的線程)暫停執行一段時間,讓其他線程有機會繼續執行,但它并不釋放對象鎖。也就是如果有synchronized同步塊,其他線程仍然不同通路共享資料。注意該方法要捕獲異常 

    比如有兩個線程同時執行(沒有synchronized),一個線程優先級為max_priority,另一個為min_priority,如果沒有sleep()方法,隻有高優先級的線程執行完成後,低優先級的線程才能執行;但當高優先級的線程sleep(5000)後,低優先級就有機會執行了。 

    總之,sleep()可以使低優先級的線程得到執行的機會,當然也可以讓同優先級、高優先級的線程有執行的機會。 

2.join() 

    join()方法使調用該方法的線程在此之前執行完畢,也就是等待調用該方法的線程執行完畢後再往下繼續執行。注意該方法也要捕獲異常。 

3.yield() 

    它與sleep()類似,隻是不能由使用者指定暫停多長時間,并且yield()方法隻能讓同優先級的線程有執行的機會。 

4.wait()和notify()、notifyall() 

    這三個方法用于協調多個線程對共享資料的存取,是以必須在synchronized語句塊内使用這三個方法。前面說過synchronized這個關鍵字用于保護共享資料,阻止其他線程對共享資料的存取。但是這樣程式的流程就很不靈活了,如何才能在目前線程還沒退出synchronized資料塊時讓其他線程也有機會通路共享資料呢?此時就用這三個方法來靈活控制。 

    wait()方法使目前線程暫停執行并釋放對象鎖标志,讓其他線程可以進入synchronized資料塊,目前線程被放入對象等待池中。當調用 notify()方法後,将從對象的等待池中移走一個任意的線程并放到鎖标志等待池中,隻有鎖标志等待池中的線程能夠擷取鎖标志;如果鎖标志等待池中沒有線程,則notify()不起作用。 

    notifyall()則從對象等待池中移走所有等待那個對象的線程并放到鎖标志等待池中。 

    注意 這三個方法都是java.lang.ojbect的方法! 

2.run()和start() 

    這兩個方法應該都比較熟悉,把需要并行處理的代碼放在run()方法中,start()方法啟動線程将自動調用 run()方法,這是由java的記憶體機制規定的。并且run()方法必須是public通路權限,傳回值類型為void。 

3.關鍵字synchronized 

    這個關鍵字用于保護共享資料,當然前提是要厘清哪些資料是共享資料。每個對象都有一個鎖标志,當一個線程通路該對象時,被synchronized修飾的資料将被“上鎖”,阻止其他線程通路。目前線程通路完這部分資料後釋放鎖标志,其他線程就可以通路了。 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<code>public</code> <code>threadtest </code><code>implements</code> <code>runnable{ </code>

<code>    </code><code>public</code> <code>synchronized</code> <code>void</code> <code>run(){ </code>

<code>        </code><code>for</code><code>(</code><code>int</code> <code>i=</code><code>0</code><code>;i&lt;</code><code>10</code><code>;i++){ </code>

<code>            </code><code>system.out.println(</code><code>" "</code> <code>+ i); </code>

<code>        </code><code>} </code>

<code>    </code><code>} </code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) { </code>

<code>        </code><code>runnable r1 = </code><code>new</code> <code>threadtest(); </code>

<code>        </code><code>runnable r2 = </code><code>new</code> <code>threadtest(); </code>

<code>        </code><code>thread t1 = </code><code>new</code> <code>thread(r1); </code>

<code>        </code><code>thread t2 = </code><code>new</code> <code>thread(r2); </code>

<code>        </code><code>t1.start(); </code>

<code>        </code><code>t2.start(); </code>

<code>}</code>

    //以上這段程式中的 i 變量并不是共享資料,也就是這裡的synchronized關鍵字并未起作用。因為t1,t2兩個線程是兩個對象(r1,r2)的線程。//不同的對象其資料是不同的,是以r1和r2兩個對象的i變量是并不是共享資料。 

    當把代碼改成如下:synchronized關鍵字才會起作用 

<code>runnable r = </code><code>new</code> <code>threadtest(); </code>

<code>    </code><code>thread t1 = </code><code>new</code> <code>thread(r); </code>

<code>    </code><code>thread t2 = </code><code>new</code> <code>thread(r); </code>

<code>    </code><code>t1.start(); </code>

<code>    </code><code>t2.start();</code>

wait()和notify(),notifyall()是object類的方法,sleep()和yield()是thread類的方法。 

(1).常用的wait方法有wait()和wait(long timeout): 

    void wait() 在其他線程調用此對象的 notify() 方法或 notifyall() 方法前,導緻目前線程等待。 

    void wait(long timeout) 在其他線程調用此對象的 notify() 方法或 notifyall() 方法,或者超過指定的時間量前,導緻目前線程等待。 

    wait()後,線程會釋放掉它所占有的“鎖标志”,進而使線程所在對象中的其它synchronized資料可被别的線程使用。 

    wait()和notify()因為會對對象的“鎖标志”進行操作,是以它們必須在synchronized函數或synchronized  block中進行調用。如果在non-synchronized函數或non-synchronized block中進行調用,雖然能編譯通過,但在運 行時會發生illegalmonitorstateexception的異常。 

(2).thread.sleep(long millis),必須帶有一個時間參數。 

    sleep(long)使目前線程進入停滞狀态,是以執行sleep()的線程在指定的時間内肯定不會被執行; 

    sleep(long)可使優先級低的線程得到執行的機會,當然也可以讓同優先級和高優先級的線程有執行的機會; 

    sleep(long)是不會釋放鎖标志的。 

(3).yield()沒有參數。 

    sleep 方法使目前運作中的線程睡眼一段時間,進入不可運作狀态,這段時間的長短是由程式設定的,yield 方法使目前線程讓出cpu占有權,但讓出的時間是不可設定的。 

    yield()也不會釋放鎖标志。 

    實際上,yield()方法對應了如下操作: 先檢測目前是否有相同優先級的線程處于同可運作狀态,如有,則把 cpu 的占有權交給此線程,否則繼續運作原來的線程。是以yield()方法稱為“退讓”,它把運作機會讓給了同等優先級的其他線程。 

    sleep方法允許較低優先級的線程獲得運作機會,但yield()方法執行時,目前線程仍處在可運作狀态,是以不可能讓出較低優先級的線程些時獲得cpu占有權。 在一個運作系統中,如果較高優先級的線程沒有調用 sleep 方法,又沒有受到 i/o阻塞,那麼較低優先級線程隻能等待所有較高優先級的線程運作結束,才有機會運作。 

    yield()隻是使目前線程重新回到可執行狀态,是以執行yield()的線程有可能在進入到可執行狀态後馬上又被執行。是以yield()隻能使同優先級的線程有執行的機會。 

特别說明:尊重作者的勞動成果,轉載請注明出處哦~~~http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp16