在各类各样的线程中,Java虚拟机必须实现一个有优先权的、基于优先级的调度程序。这意味着Java程序中的每个线程被分配到必定的优先权,使用定义好的范围内的一个正整数表示。优先级能够被开发者改变。即便线程已经运行了必定时间,Java虚拟机也不会改变其优先级java
优先级的值很重要,由于Java虚拟机和下层的操做系统之间的约定是操做系统必须选择有最高优先权的Java线程运行。因此咱们说Java实现了一个基于优先权的调度程序。该调度程序使用一种有优先权的方式实现,这意味着当一个有更高优先权的线程到来时,不管低优先级的线程是否在运行,都会中断(抢占)它。这个约定对于操做系统来讲并不老是这样,这意味着操做系统有时可能会选择运行一个更低优先级的线程。(我憎恨多线程的这一点,由于这不能保证任何事情)多线程
接下来,理解线程优先级是多线程学习很重要的一步,尤为是了解yield()函数的工做过程。函数
如今,当咱们对线程调度和线程优先级有必定理解后,让咱们进入主题。学习
理论上,yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其余线程占用本身的位置。这代表该线程没有在作一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。this
让咱们列举一下关于以上定义重要的几点:spa
在下面的示例程序中,我随意的建立了名为生产者和消费者的两个线程。生产者设定为最小优先级,消费者设定为最高优先级。在Thread.yield()注释和非注释的状况下我将分别运行该程序。没有调用yield()方法时,虽然输出有时改变,可是一般消费者行先打印出来,而后事生产者。操作系统
调用yield()方法时,两个线程依次打印,而后将执行机会交给对方,一直这样进行下去。线程
线程实例的方法join()方法可使得一个线程在另外一个线程结束后再执行。若是join()方法在一个线程实例上调用,当前运行着的线程将阻塞直到这个线程实例完成了执行。code
1
2
3
|
//Waits for this thread to die.
public
final
void
join()
throws
InterruptedException
|
在join()方法内设定超时,使得join()方法的影响在特定超时后无效。当超时时,主方法和任务线程申请运行的时候是平等的。然而,当涉及sleep时,join()方法依靠操做系统计时,因此你不该该假定join()方法将会等待你指定的时间。blog
像sleep,join经过抛出InterruptedException对中断作出回应。
1 package test.core.threads; 2 3 public class JoinExample 4 { 5 public static void main(String[] args) throws InterruptedException 6 { 7 Thread t = new Thread(new Runnable() 8 { 9 public void run() 10 { 11 System.out.println("First task started"); 12 System.out.println("Sleeping for 2 seconds"); 13 try 14 { 15 Thread.sleep(2000); 16 } catch (InterruptedException e) 17 { 18 e.printStackTrace(); 19 } 20 System.out.println("First task completed"); 21 } 22 }); 23 Thread t1 = new Thread(new Runnable() 24 { 25 public void run() 26 { 27 System.out.println("Second task completed"); 28 } 29 }); 30 t.start(); // Line 15 31 t.join(); // Line 16 32 t1.start(); 33 } 34 } 35 36 Output: 37 38 First task started 39 Sleeping for 2 seconds 40 First task completed 41 Second task completed