您的位置:首页 > 其它

线程状态流转图

2015-07-22 20:51 253 查看
Java线程内部流转过程

Java线程内部的状态流转过程是什么样子的,下图给出了一个详细的图例说明。

(1) Thread t = new Tread(); 当执行到此段代码时,jvm生成一个新的线程对象,此时该线程处于初始状态。

(2) 当线程处于可运行状态时,该线程未必就能得到立即执行,这取决于该线程是否获得了cpu的运行时间片。当获得了时间片,该线程得到执行,处于运行状态。

(3) 处于运行状态的线程最理想的情况是run()方法运行结束,或者抛出异常,整个线程结束。实际常常发生的情况是线程的执行过程会进入阻塞或者等待队列中去。

(4)当线程处于运行状态时,有4种状态可以流转:(1)结束(2)可运行(3)阻塞(4)进入等待池。详见图上标注。这里需要搞明白yield()、sleep()、wait()这些方法的含义。

yield()、sleep()的区别

这两者的都是使得当前线程暂停运行,且都不会释放锁,两者都会在进入对应状态结束后重新执行。区别在于yield放弃当前执行时间,此时同优先级别的线程(非依赖当前锁的线程)可能会得到执行;而sleep则可以让低于自己优先级的线程(非依赖当前锁的线程)得到执行。yield的内部逻辑是:先检测是否有相同优先级别的线程处于可运行状态,如果有让出cup使用权,否则当前线程继续执行。所以yield的线程可能会从可运行状态立即回到运行状态。

两个重要的概念

锁池

对象myObject已经被某个线程A持有,那么当其他的线程B/C/D等想要来调用myObject的某个加了synchronized的修饰符的方法或者方法块内部有synchronized,此时线程B/C/D就进入了myObject的锁池,这里的池和线程池是一样的概念。

等待池

首选需要了解下java和线程有关的wait和notify,以及notifyAll()方法的含义。wait、notify(),notifyAll()都是Object类的方法,而不是线程的方法,这么做的目的便于线程控制,因为一个线程可能会涉及到多个锁,把锁设置为对象的属性,更易于控制。

当线程A获得了myObject的锁后,此时如果调用wait()方法,则线程A会释放掉该锁,此时线程A进入myObject的等待池。注意调用wait方法一定是在synchronized方法中的,因为前提是线程获得了myObject对象的锁。

线程B/C/D此时会进行锁的争夺,当线程B获得了锁后,并调用notify(),此时线程A会会进入锁池,当前锁池中又线程A/C/D三个线程,至于是哪个来获得锁,由操作系统的调度算法决定。

wait()、notify()、notifyAll()主要用于多个线程需要相互交互相互依赖的场景,比如生产者消费者,此时锁对象一般是队列。

所以等待池是当线程主动释放掉锁时会进入一个等待状态的集合。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: