java线程中yield()和join()的区别

来源:互联网 发布:淘宝与描述相符评分 编辑:程序博客网 时间:2024/04/30 23:33

多线程在面试中是非常受欢饮的题目,我个人认为我们很少有机会能够真正的用到复杂的多线程(我在7年前使用过一次),熟悉这些概念能够增加你的信心,先前,我已经讨论了一个相似的问题,wait()和sleep()的区别。现在我们讨论一下join()和yield()的区别。坦白的讲,我在实际中比没有用过这两种方法,如果你觉得有问题请在评论中提出来

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 startedSleeping for 2 secondsFirst task completedSecond 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
0 0
原创粉丝点击