長期以來,多線程問題頗爲受到面試官的青睞。雖然我我的認爲咱們當中不多有人能真正得到機會開發複雜的多線程應用(在過去的七年中,我獲得了一個機會),可是理解多線程對增長你的信心頗有用。以前,我討論了一個wait()和sleep()方法區別的問題,這一次,我將會討論join()和yield()方法的區別。坦白的說,實際上我並無用過其中任何一個方法,因此,若是你感受有不恰當的地方,請提出討論。java
在各類各樣的線程中,Java虛擬機必須實現一個有優先權的、基於優先級的調度程序。這意味着Java程序中的每個線程被分配到必定的優先權,使用定義好的範圍內的一個正整數表示。優先級能夠被開發者改變。即便線程已經運行了必定時間,Java虛擬機也不會改變其優先級面試
優先級的值很重要,由於Java虛擬機和下層的操做系統之間的約定是操做系統必須選擇有最高優先權的Java線程運行。因此咱們說Java實現了一個基於優先權的調度程序。該調度程序使用一種有優先權的方式實現,這意味着當一個有更高優先權的線程到來時,不管低優先級的線程是否在運行,都會中斷(搶佔)它。這個約定對於操做系統來講並不老是這樣,這意味着操做系統有時可能會選擇運行一個更低優先級的線程。(我憎恨多線程的這一點,由於這不能保證任何事情)多線程
注意Java並不限定線程是以時間片運行,可是大多數操做系統卻有這樣的要求。在術語中常常引發混淆:搶佔常常與時間片混淆。事實上,搶佔意味着只有擁有高優先級的線程能夠優先於低優先級的線程執行,可是當線程擁有相同優先級的時候,他們不能相互搶佔。它們一般受時間片管制,但這並非Java的要求。函數
接下來,理解線程優先級是多線程學習很重要的一步,尤爲是瞭解yield()函數的工做過程。學習
如今,當咱們對線程調度和線程優先級有必定理解後,讓咱們進入主題。this
理論上,yield意味着放手,放棄,投降。一個調用yield()方法的線程告訴虛擬機它樂意讓其餘線程佔用本身的位置。這代表該線程沒有在作一些緊急的事情。注意,這僅是一個暗示,並不能保證不會產生任何影響。spa
在Thread.java中yield()定義以下:操作系統
1
2
3
4
5
6
7
|
/**
* 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();
|
讓咱們列舉一下關於以上定義重要的幾點:線程
在下面的示例程序中,我隨意的建立了名爲生產者和消費者的兩個線程。生產者設定爲最小優先級,消費者設定爲最高優先級。在Thread.yield()註釋和非註釋的狀況下我將分別運行該程序。沒有調用yield()方法時,雖然輸出有時改變,可是一般消費者行先打印出來,而後事生產者。code
調用yield()方法時,兩個線程依次打印,而後將執行機會交給對方,一直這樣進行下去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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();
}
}
}
|
1
2
3
4
5
6
7
8
9
10
|
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
|
1
2
3
4
5
6
7
8
9
10
|
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()方法在一個線程實例上調用,當前運行着的線程將阻塞直到這個線程實例完成了執行。
1
2
3
|
//Waits for this thread to die.
public
final
void
join()
throws
InterruptedException
|
在join()方法內設定超時,使得join()方法的影響在特定超時後無效。當超時時,主方法和任務線程申請運行的時候是平等的。然而,當涉及sleep時,join()方法依靠操做系統計時,因此你不該該假定join()方法將會等待你指定的時間。
像sleep,join經過拋出InterruptedException對中斷作出迴應。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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();
}
}
Output:
First task started
Sleeping
for
2
seconds
First task completed
Second task completed
|
這是一些很小卻很重要的概念。在評論部分讓我知道你的想法。