java线程的几种状态

线程共有6种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。分别对应于:新建、运行、阻塞、等待、带超时的等待、终止。

1)新建状态(New)
当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

2)就绪状态(Runnable)
当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

3)运行状态(Running)
当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

4)阻塞状态(Blocked)
处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1、等待阻塞
运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2、同步阻塞
线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3、其他阻塞
通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5)死亡状态(Dead)
线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

用一张图来将其概括的话会更容易记忆:

 

1)正常情况
如上图中红色箭头所示,正常状态下线程的声明周期是这样的:NEW -> RUNNABLE -> RUNNING -> DEAD。

分别是正常情况(红色箭头),发生锁阻塞(同步阻塞)的情况(蓝色箭头),发生等待阻塞的情况(黄色箭头),发生其他阻塞的情况(黑色箭头),分别对应上图4个不同颜色的流向。

2)发生锁阻塞(同步阻塞)
如上图中蓝色箭头所示,当线程进入 RUNNING 状态时进入了 synchronized 方法块,这时就会发生锁阻塞,线程进入一个 Lock Pool 锁池中。当其获得锁之后,又进入到可运行状态。当CPU分片轮询到它的时候,它就再次运行,直至 DEAD 状态。

3)发生等待阻塞
如上图中蓝色箭头所示,当线程进入 RUNNING 状态时遇到了 wait() 方法,这时就会发生等待阻塞,它会等待其他线程调用 notify() 方法释放锁之后才可恢复到可运行状态。当CPU分片轮询到它的时候,它就再次运行,直至 DEAD 状态。等待阻塞和锁阻塞其实是同一类型的,都是因为争夺锁而发生的线程等待,唯一的不同是因为它们调用的是不同的方式实现,但底层原理相同。要注意的是执行 wait() 方法的时候,线程一定要获得锁,所以 wait() 方法一般都在 synchronized 方法或代码块中。当其获得锁之后进入等待池(wait pool)并释放锁。收到 notify() 通知之后等待获取锁,获取锁之后才可以运行。

4)发生其他阻塞(如:IO读取等)
当线程需要去读取文件,而此时文件又被其他线程占用,那么就会发生阻塞。这时候线程需要等待其他线程读取完之后才能继续进行,这可以称为 IO 阻塞。当然了还有很多种情况,如网络阻塞等等。

状态变为等待可以有以下几种方式:

1、Object里面的wait()方法//很常用

2、Thread.join()方法//很常用

3、LockSupper.park()//

状态变为超时等待有以下几种方式:

1、Thread.sleep(long)方法//很常用

2、Object.wait(long)方法//跟wait()不一样

3、Thread.join(long)方法//跟Thread.join()不一样

4、LockSupper.parkNanos// 重点

5、LockSupper.parkUntil// 重点
 

LockSupper.parkxxx()的使用最经典的是JDK5并发包,

1、在lock的时候如果失败,使线程等待;

2、在Lock实例的newCondition()对象Condition.await()。——相似于Object的wait()但更为强大,可以在等待期间不响应中断

    无论是Object.wait()被Object.notify(),Thread.interrupt()还是Condition.await()被Conditon.signal(),Thread.interrupt()都会使被唤醒线程状态由WAITING、TIMED_WAITING 先转为BLOCKED,因为此时唤醒线程并没有释放锁。
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个学编程的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值