一个线程有多种状态,
1、新建(new):创建后尚未启动的线程处于这种状态;
2、运行(runnable):包括running和ready,正在运行或者等待cpu分配时间片。运行中通过执行yield进入就绪态:让出时间片(并非锁)给优先级更高的线程,没有的话就继续执行
3、无限期等待(waitiing):不会被分配时间片,要等待其他线程显式的唤醒并释放锁或中断才可返回,涉及到以下方法:无时间的object.wait() 无时间的 Thread.join() LockSupport.park()
4、有期限的等待(timed_waiting):不会被分配时间片,被其他线程显式唤醒释放锁或者等待一定时间由操作系统自动唤醒,涉及到以下方法: 有时间的object,wait() 有时间的Thread.join() LockSupport.parkNanos() LockSupport.parkUnit()
5、阻塞(blocked):线程为获取到锁而阻塞在同步块之外,它在等待一个排它锁
6、终止(terminated):以终止线程的线程状态,线程已经结束执行
相信大家对waiting和blocked一定很疑惑,那么他们的区别到底在哪里呢?
阻塞状态:线程被动的进入这种状态,由于获取锁失败,所以此时它并没有进入同步代码块!
等待状态:由于业务需求或条件,线程主动暂时释放锁,立刻进入等待队列,注意线程已经获取到了锁,成功进入代码块。等待着条件成熟会再次获取锁。
下面借用一张图来更直观说明:图中左侧为阻塞态(未拿到锁),右侧为等待态(拿到锁后暂时释放,条件成熟会再次获取锁)
除此之外再说一下sleep方法和wait/notify方法的区别:
sleep方法是定义在Thread上的native方法, 在设定的时间内阻塞线程执行,但是不改变线程持有锁的情况
而wait方法是定义在object类上的方法,是Java语言级别的方法,执行前需要先对调用对象加锁,也就是说wait和notify方法必须在同步代码块或者同步方法中执行。然后该线程会释放锁并进入锁对象的等待队列,需要等待其他线程释放锁并执行notify方法以后才会醒来。注意:即使其他线程notify了它也不一定醒来,必须锁释放之后才会醒,也就是notify并且同步代码块执行完毕waiting的线程才会醒过来。
需要说明的是:waiting线程被唤醒之后,会由等待队列进入到同步队列,也就是由等待状态进入阻塞态,从而重新竞争锁。
总而言之,它们都不会继续占用cpu时间片,不过前者是受cpu计时器的调度,而后者受java语言其他线程的调度