JAVA线程(二)
JAVA 中的一个线程只有六个状态,在源码State枚举类中体现。这个枚举一共有6个值NEW(新建),RUNNABLE(运行),BLOCKED(锁池更贴近源码意思点)有的称为阻塞状态
WAITING(等待),TERMINATED(终止,结束)。但是为了理解,加入了阻塞,可运行,挂起状态。
线程的状态转换:
当一个线程创建以后,就处于新建状态,那么什么时候这个状态会改变。只要它调用了start方法,那么线程就进入了锁池状态.
进入到锁池以后就会参与锁的竞争,当它获得锁以后还不能马上运行,因为一个单核CPU在某一时刻,只能执行一个线程,所以它还需要操作系统分配给它的时间片,才行执行。所以可以把一个线程获取锁之后,在获得时间片之前称为可运行状态(源码没有人们为了方便理解自己加的)。
当一个持有对象锁的线程获得CPU时间片以后,开始执行这个线程,此时叫做运行状态。
当一个线程正常执行完以后,那么就会进入死亡状态,系统就会回收这个线程占用的资源。
但是线程的执行并不是那么顺利的。一个正在执行的线程有可能执行一些I/O交互,还可以调用sleep方法,还有可能在当前线程中有其他线程调用了join方法。这时候线程就进入阻塞状态(源码没有人们为了方便理解自己加的)。阻塞状态的线程是没有释放对象锁的。当I/O交互完成后,或者sleep方法完成。或其他调用join方法的线程执行完毕。阻塞状态的线程就会恢复到可运行状态,此时如果再次获得CPU时间片就会进入运行状态。
一个处于运行状态的线程还可能调用wait方法,或者带时间参数的wait(long milli)方法,这时候线程就会将对象锁释放。进入等待队列里面(如果是调用wait()方法则进入等待状态),如果是调用带时间参数的则进入定时等待状态。
一个线程如果调用的是带时间参数的wait方法进入定时等待状态,那么只要时间一到就会进入锁池状态,并不需要notify()和notifyAll()方法来唤醒它,如果调用的是不带时间参数的wait则需要notify或notifyAll这两个方法来唤醒它然后进入锁池状态,进入锁池状态以后还要继续参与锁的竞争。
当一个处于运行状态的线程调用suspend()方法以后,它就会进入挂起状态(已经过时了)。挂起状态的线程也没释放对象锁,它需要调用resume方法以后才能恢复到可运行状态。将线程挂起容易导致程序死锁。
下面是我自己画的线程状态转换图: