java线程中yield()和join()的区别
2015-12-08 11:26
621 查看
多线程在面试中是非常受欢饮的题目,我个人认为我们很少有机会能够真正的用到复杂的多线程(我在7年前使用过一次),熟悉这些概念能够增加你的信心,先前,我已经讨论了一个相似的问题,wait()和sleep()的区别。现在我们讨论一下join()和yield()的区别。坦白的讲,我在实际中比没有用过这两种方法,如果你觉得有问题请在评论中提出来
优先级的值很重要,因为这是java虚拟机和底部的操作系统的契约,操作系统必须选择一个最高优先级的java线程运行。这就是我们平时讲的java实现了一个priority-based的调度。调度的实现使用的是preemptive方式,也就是说高优先级的线程来到之后,不管低优先级的线程是否运行线程都会中断。然而和操作系统间的契约并不是绝对的,操作系统也可以选择低优先级的线程运行【我很讨厌多线程的这点,没有什么是保证的】
1、在不指定的情况下,所有的线程的优先级都是正常的。
2、优先级的范围从1到10,10是最高优先级,1是最低优先级,5是正常优先级。
3、最高优先级的线程有执行的趋向,但是不能保证这一线程一定会在它开始的时候执行。
4、当前执行的线程和线程池中等待的线程相比或许有比较高的优先级。
5、线程调度决定哪个线程执行
6、t.setPriority()可以被用来设置线程的优先级
7、线程的优先级应该在start()方法调用之前被设置
8、你可以使用常量MIN_PRIORITY,MAX_PRIORITY and NORM_PRIORITY来设置优先级
现在我们队对线程的调度和线程的优先级有了基本的了解,开始进入主题
在Thread.java中yield是这样定义的
我们列一下上边定义的一些重要的点
1、yield的是静态方法也是native方法
2、yield告诉正在执行的线程给线程池中有相同优先级的线程一个机会
3、yield不能保证正在执行的线程立刻变成Runnable状态
4、它仅仅可以使一个线程从running状态变成Runnable状态,而不是wait或者blocked状态
使用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方法中设定超时,可以设定在指定的时间内无效。当超时到达,主线程和任务线程都可能被执行,但是,因为有sleep,join需要根据OS的时间规定来执行,所以你不应该假定线程和你指定的时间是一样的
和sleep一样,Join相应中断
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
这就是一个很小但是很重要的概念的全部。
原文地址:http://howtodoinjava.com/2014/06/03/difference-between-yield-and-join-in-threads-in-java/
也可参考:http://uule.iteye.com/blog/1101994
java 线程调度的背景
java虚拟机要求在多线程中实现 preemptive和priority-based调度,这意味着java中每一个线程被分配了特定的优先级,正整数在定义好的范围内不断减。优先级可以通过开发者改变但是java虚拟机从不改变线程的优先级,即使线程已经运行了一段时间。优先级的值很重要,因为这是java虚拟机和底部的操作系统的契约,操作系统必须选择一个最高优先级的java线程运行。这就是我们平时讲的java实现了一个priority-based的调度。调度的实现使用的是preemptive方式,也就是说高优先级的线程来到之后,不管低优先级的线程是否运行线程都会中断。然而和操作系统间的契约并不是绝对的,操作系统也可以选择低优先级的线程运行【我很讨厌多线程的这点,没有什么是保证的】
理解线程的优先级
理解线程的优先级是学习多线程特别是yield怎么工作的下一个重要的步骤。1、在不指定的情况下,所有的线程的优先级都是正常的。
2、优先级的范围从1到10,10是最高优先级,1是最低优先级,5是正常优先级。
3、最高优先级的线程有执行的趋向,但是不能保证这一线程一定会在它开始的时候执行。
4、当前执行的线程和线程池中等待的线程相比或许有比较高的优先级。
5、线程调度决定哪个线程执行
6、t.setPriority()可以被用来设置线程的优先级
7、线程的优先级应该在start()方法调用之前被设置
8、你可以使用常量MIN_PRIORITY,MAX_PRIORITY and NORM_PRIORITY来设置优先级
现在我们队对线程的调度和线程的优先级有了基本的了解,开始进入主题
yield方法
理论上讲,yield的意思是松开,放弃或者是屈服。一个yielding的线程告诉虚拟机它允许其他的线程被调度它现在所在的位置,这意味着它没有严格的做一些事情。注意这只是一个线索,没有保证什么事情。在Thread.java中yield是这样定义的
/** * 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不能保证正在执行的线程立刻变成Runnable状态
4、它仅仅可以使一个线程从running状态变成Runnable状态,而不是wait或者blocked状态
yield()方法使用的例子
在下边的程序中,我创建了两个线程一个是producer一个是consumer。producer设置最小的优先级,consumer设置最高的优先级,在使用和不使用yield方法的条件下运行下边的代码,尽管输出有时候会改变,但是通常情况下首先是consumer全部打印,其次是producer全部打印使用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到线程执行的开始和其他线程执行的结束,所以直到其他线程运行结束这个线程才会执行。如果join的方法在线程实例中被调用,当前运行的线程会被堵塞,直到线程实例运行完成//Waits for this thread to die. public final void join() throws InterruptedException
在join方法中设定超时,可以设定在指定的时间内无效。当超时到达,主线程和任务线程都可能被执行,但是,因为有sleep,join需要根据OS的时间规定来执行,所以你不应该假定线程和你指定的时间是一样的
和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(); } } Output: First task started Sleeping for 2 seconds First task completed Second task completed
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
这就是一个很小但是很重要的概念的全部。
原文地址:http://howtodoinjava.com/2014/06/03/difference-between-yield-and-join-in-threads-in-java/
也可参考:http://uule.iteye.com/blog/1101994
相关文章推荐
- Eclipse 常用快捷键
- JAVA虚拟机干货
- maven 把spring项目打包成可执行的文件
- java泛型程序设计——Varargs 警告+不能实例化类型变量
- 1003. 我要通过!(20) JAVA pattern
- java泛型类和泛型函数
- Java—字符串小结
- javaWeb中的文件上传下载
- 1002. 写出这个数 (20) JAVA
- JAVA中String及常用操作函数
- Java I/O— 梳理各种“流”
- 1001. 害死人不偿命的(3n+1)猜想 (15) java
- java 突击队注意事项:在路上
- Java双缓冲
- Eclipse+Jersey实现RESTful服务
- Eclipse读取xml中文乱码问题解决
- Java Base —— 注解
- Java 中有关数组的操作
- Day_7访问权限
- java对Json字符串的格式化输出