线程生命周期状态
在java中,任何对象都要有生命周期,线程也不例外,他也有自己的生命周期,当thread对象创建完成时,线程的生命周期便开始了,当run()方法中代码正常执行完成或者抛出一个未捕获的异常Exception或者是错误时,Error,线程生命周期便会结束,线程的整个生命周期可以分为6个阶段,传统线程模型中线程状态分为5个
- 新建状态(New)
- 就绪状态(Runnable)
- 运行状态(Running)
- 阻塞状态(Blocked)
- 死亡状态(Terminated)
线程不同状态表明了线程当前正在进行的活动.在程序中通过一些操作可以使线程在不同状态之间转换
上图中展示了线程各种状态的转换关系,箭头表示可转换的方向,其中但箭头表示状态只能单向转换,列入线程只能从新建状态转换到就绪状态
java中有6种状态
传统线程模型(操作系统)中线程状态
新建状态New
创建一个线程对象后,该线程对象就处于新建状态,此时它不能运行,与其他的JAva对象一样,仅仅由java虚拟机为其分配了内存,没有表现出任何线程的动态特征
就绪状态Runnable
当线程对象调用了start方法后,该线程就进入就绪状态.处于就绪状态的线程位于线程队列中,此时它只是具备了运行的条件,能否获得CPU的使用权并开始运行,还需要等待系统的调度
运行状态Running
如果处于就绪状态的线程获取了cpu的使用权,并执行run()方法总的线程执行体,则该线程处于运行状态我.一个线程启动会,它可能不会一直处于运行状态,当运行状态的线程使用完系统分配的时间后,系统就会剥夺该线程占用的cpu资源让其他线程活得执行的机会,需要注意的是,只有处于就绪状态的线程才可能转换到运行状态
阻塞状态 Blocked
一个正在执行的线程在某些特殊情况下,如果被人为的挂起或执行耗时的输入/输出操作时,会让出CPU的使用权并暂时中止自己的执行,进入阻塞状态我.线程进入阻塞状态后,就不能进入排队队列.只有当引起阻塞的原因被消除后,线程才可以转入就绪状态
下面列举转换成阻塞状态的原因,以及如何从阻塞状态转换成就绪状态
- 当线程属兔获取某个对象的同步锁时,如果该锁被其他线程持有,当前线程就会进入阻塞状态,如果想从阻塞状态进入就绪状态就必须获取到其他线程持有的锁
- 当线程调用了一个阻塞式I/O方法时,该线程就会进入阻塞状态,如果想进入就绪状态就必须要等这个阻塞I/O方法返回
- 当调用了某个对象的wait()方法时,也会使线程进入阻塞状态,如果想进入就绪状态就需要使用notify()方法唤醒该线程
- 当调用了Thread的sleep(long millis)方法时,也会进入阻塞状态,在这种情况下,只需要到线程睡眠的时间了后,线程就会自动进入就绪状态
- 当一个线程调用了另一个线程的join()方法时,会使当前线程进入阻塞状态,在这种情况下,需要等到新加入的线程运行结束后才会结束阻塞状态进入就绪状态
需要注意的是,线程从阻塞状态只能进入就绪状态,而不能直接进入运行状态,也就是说,结束阻塞的线程需要重新进入可运行池中,等待系统的调度
Sleep和wait的异同
- wait和sleep方法都可以使线程进入阻塞状态
- wait和sleep方法均是可中断方法,被中断后都会受到异常
不同
- wait是Object方法,sleep是thread特有方法
- wait方法执行必须在同步方法中进行,sleep不需要
- 线程在同步方法执行sleep方法时,并不会释放monotor锁,而wait方法则会释放monitor锁,并且将线程添加到对象监视器中(monitor)的等待队列中
- sleep方法短暂休眠之后会主动退出阻塞,而wait方法(没有指定wait时间)则需要被其他线程中断后才能退出阻塞。
- sleep不需要被唤醒,但是wait是需要唤醒的
死亡状态 Dead
如果线程调用stop()方法或者run()方法正常执行完毕,或者线程抛出一个未捕获的异常或者错误,线程就进入死亡状态,一旦进入死亡状态,线程不再拥有 运行的资格,也不能转换到其他状态
java线程中的状态
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
我们可以看到实际上是分为6种状态的
初始状态(NEW)
线程被构建,但是还没有调用start方法
运行状态(RUNNABLE)
java把操作系统中就绪和运行俩种状态统一为运行中
阻塞状态(BLOCKED)
表示该线程进入等待状态,也就是线程因为某种原因放弃了CPU的使用权,阻塞也分为几种情况
- 等待阻塞:运行的线程执行了Thread.sleep,wait,join等方法,JVM会把当前线程设置为等待状态,当sleep结束,join线程终止或者被唤醒后,该线程从等待状态进入阻塞状态,重新占用锁后进行线程恢复
- 同步阻塞:运行的线程在获取对象的同步锁时,若改同步锁被其他线程锁占用了,那么当前JVM会把当前线程放到锁池中
- 其他阻塞:发出I/O请求,JVM会把当前线程设置为阻塞状态,当I/O处理完毕则线程恢复
等待(WATING)
等待状态,没有超时时间(无线等待),要被其他线程或者有其他的中断操作
执行wait,join,lockSuport.park
超时等待(TIME_WAITING)
与等待不同的是,不是无限等待,超时等待是超时后自动返回
执行sleep,带参数的wait等待可以实现
终止(TEMINATED)
代表线程创建完毕