對線程優先順序的理解
對線程的優先順序的理解對於多線程的學習和yield()工作原理的理解非常有協助。
1、如果沒有具體指定優先順序,那麼所有線程優先順序都屬於普通優先順序。
2、優先順序分為1到10這十個等級,其中10是最高優先順序,1是最低優先順序,5屬於普通優先順序。
3、具有最高優先順序的線程將會優先被執行,但是這並不能保證它在啟動的時候就是運行狀態。
4、對於線上程池中等待被調度的線程來說,當前執行的線程可能有更高的優先順序。
5、決定哪個線程應該被執行的是線程調度者。
6、t.setPriority()方法可以用於設定線程的優先順序。
7、線程的優先順序應該線上程的start方法調用之前被設定。
8、可以使用常量MIN_PRIORITY,MAX_PRIORITY 和 NORM_PRIORITY來設定優先權。
yield()方法
調用yield方法就是表示線程告訴虛擬機器,它願意讓其他的線程在這個地方被調度,也就是它可以讓出當前執行的時間片,但它並不會使當前線程阻塞,下個時間片它可能會被繼續執行,這表明該線程沒有在做一些緊急的事情。注意,這僅是一個暗示,並不能保證不會產生任何影響。
下面是yield()在Thread.java中的定義
/** * A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore * this hint. Yield is a heuristic attempt to improve relative progression between threads that would otherwise over-utilize a CPU. * Its use should be combined with detailed profiling and benchmarking to ensure that it actually has the desired effect. */public static native void yield();
下面有重要的幾點:
1、Yield是一個靜態原生(native)方法
2、Yield 告訴當前執行的線程可以給一個機會給線程池中有相同優先順序的線程,讓它們被調度。
3、Yield不能保證使得當前正在啟動並執行線程迅速轉換到可啟動並執行狀態
4、它僅能使一個線程從運行狀態轉到可運行狀態,而不是等待或阻塞狀態
在下面的樣本程式中,我隨意的建立了名為生產者和消費者的兩個線程。生產者設定為最小優先順序,消費者設定為最高優先順序。在Thread.yield()注釋和非注釋的情況下我將分別運行該程式。沒有調用yield()方法時,雖然輸出有時改變,但是通常消費者行先列印出來,然後事生產者。
package test.core.threads;public class YieldExample{ public static void main(String[] args) { Thread producer = new Producer(); Thread consumer = new Consumer(); producer.setPriority(Thread.MIN_PRIORITY); //Min Priority consumer.setPriority(Thread.MAX_PRIORITY); //Max Priority producer.start(); consumer.start(); }}class Producer extends Thread{ public void run() { for (int i = 0; i < 5; i++) { System.out.println("I am Producer : Produced Item " + i); Thread.yield(); } }}class Consumer extends Thread{ public void run() { for (int i = 0; i < 5; i++) { System.out.println("I am Consumer : Consumed Item " + i); Thread.yield(); } }}
沒有yield()方法時的輸出結果:
I am Consumer : Consumed Item 0 I am Consumer : Consumed Item 1 I am Consumer : Consumed Item 2 I am Consumer : Consumed Item 3 I am Consumer : Consumed Item 4 I am Producer : Produced Item 0 I am Producer : Produced Item 1 I am Producer : Produced Item 2 I am Producer : Produced Item 3 I am Producer : Produced Item 4
有yield()方法時的輸出結果:
I am Producer : Produced Item 0 I am Consumer : Consumed Item 0 I am Producer : Produced Item 1 I am Consumer : Consumed Item 1 I am Producer : Produced Item 2 I am Consumer : Consumed Item 2 I am Producer : Produced Item 3 I am Consumer : Consumed Item 3 I am Producer : Produced Item 4 I am Consumer : Consumed Item 4
join()方法
一個線程執行個體的join方法可以將一個線程的執行加入到另一個線程中,使得只有加入的線程執行完畢之後,當前線程才能進行運行。如果join方法被一個執行個體線程調用,那麼當前線程就會處於阻塞狀態,直到這個執行個體線程執行完畢。
//Waits for this thread to die.public final void join() throws InterruptedException
在join()方法內設定逾時,使得join()方法的影響在特定逾時後無效。當逾時時,主方法和任務線程申請啟動並執行時候是平等的。然而,當涉及sleep時,join()方法依靠作業系統計時,所以你不應該假定join()方法將會等待你指定的時間。
package test.core.threads;public class JoinExample{ public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new Runnable() { public void run() { System.out.println("First task started"); System.out.println("Sleeping for 2 seconds"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("First task completed"); } }); Thread t1 = new Thread(new Runnable() { public void run() { System.out.println("Second task completed"); } }); t.start(); // Line 15 t.join(); // Line 16 t1.start(); }}
輸出結果:
First task startedSleeping for 2 secondsFirst task completedSecond task completed
原文連結:Difference between yield() and join() in threads in java?