长期以来,多线程问题颇为受到面试官的青睐。虽然我我的认为咱们当中不多有人能真正得到机会开发复杂的多线程应用(在过去的七年中,我获得了一个机会),可是理解多线程对增长你的信心颇有用。以前,我讨论了一个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
|
这是一些很小却很重要的概念。在评论部分让我知道你的想法。