线程状态之间的变化+run、start、sleep与wait

本文详细阐述了Java线程的不同状态(新建、可运行、终结)、线程间的同步与通信(如阻塞、等待、有时限等待),以及start与run方法的区别,强调了wait、sleep和notify的差异,包括归属、唤醒时机和锁特性。

新建:当一个线程对象被创建,但还未调用start方法时处于新建状态,此时未与操作系统底层线程关联。

可运行:调用了start方法,就会由新建状态进入到可运行状态,此时与底层线程关联,由操作系统调度执行。

终结:线程内代码已经执行完毕,即run方法之后,就由运行状态进入到终结状态,此时会取消与底层线程关联。

这是一条正常的流程,但是代码在运行状态下可以因为一些原因进入到其它状态,比如:

阻塞:当获取锁失败后,由可运行进入Monitor的阻塞队列阻塞,此时不占用cpu时间。当持有锁的线程释放锁时,会按照一定规则唤醒阻塞队列中的阻塞线程,唤醒后的线程进入可运行状态

等待:当获取锁成功后,由于条件不满足,调用了wait()方法,此时从可运行状态释放锁进入Monitor等待集合等待,同样不占用cpu时间。当其它持有锁的线程调用notify()或notifyAll()【notifyAll唤醒所有wait线程||notify只随机唤醒一个wait线程】方法,会按照一定规则唤醒等待集合中的等待线程,回复为可运行状态。

有时限等待(计时等待):当获取锁成功后,但由于条件不满足,调用了wait(long)方法,此时从可运行状态释放锁进入Monitor等待集合进行有时限等待,同样不占用cpu时间。当其它持锁线程调用notify()或notifyAll()方法,会按照一定规则唤醒等待集合中的有时限等待线程,恢复为可运行状态,并重新去竞争锁。如果等待超时,也会从有时限等待状态恢复为可运行状态,并重新去竞争锁。+ 还有一种情况是调用sleep(long)方法也会从可运行状态进入有限等待状态,但是与Monitor无关,不需要主动唤醒,超时时间到了就会自然恢复为可运行状态。

注意run()和start()的区别:start()方法是用来启动线程的,通过该线程调用run方法执行run方法中所定义的逻辑代码,start方法只能被调用一次。run()方法封装了要被线程执行的代码,可以被调用很多次。

上述中wait与sleep也要重点区分:wait、wait(long)和sleep(long)的效果都是让当前线程放弃cpu的使用权,进入阻塞状态。但是它们有以下不同:

方法归属不同:sleep(long)是Thread的静态方法,而wait()、wait(long)都是Object的成员方法,每个对象都有。

醒来时机不同:执行sleep(long)和 wait(long)的线程都会在等待相应的毫秒后醒来。wait(long)和wait()都可以被notify唤醒,wait()如果不唤醒就一直等下去,并且它们都可以被打断唤醒

锁特性不同:wait方法的调用必须先获取wait对象的锁,而sleep无此限制。wait方法执行后释放对象锁,允许其它线程获取该对象锁(别人可以用cpu)。而sleep如果在synchronized代码块中执行,并不会释放对象锁(别人用不了cpu)。

<think>好的,我需要回答用户关于Java线程状态转换的问题。首先,用户提到了几个引用内容,我需要仔细看看这些引用里的信息,然后整理出一个清晰的解释。 根据引用[1]和[2],Java线程有六个状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。NEW状态线程刚被创建但还没启动的时候。当调用start()方法后,线程进入RUNNABLE状态,这里要注意RUNNABLE其实包括了操作系统中的就绪(Ready)和运行中(Running)两种状态,因为是否真正执行取决于CPU时间片的分配。 引用[5]提到,当线程调用Thread.sleep(long n)时,会从RUNNABLE进入TIMED_WAITING状态。类似的方法还有Object.wait()带超时的情况。而进入BLOCKED状态通常是因为线程在等待进入同步块或方法,比如获取锁的时候。WAITING状态则是通过调用Object.wait()、Thread.join()等方法,没有超时时间的等待。 接下来,状态之间的转换需要详细说明。比如,从RUNNABLE到BLOCKED可能是在等待锁的时候,而获取到锁后又回到RUNNABLE。WAITING和TIMED_WAITING的区别在于是否有超时时间,它们的触发方法不同,比如wait()不带参数会导致WAITING,带参数则进入TIMED_WAITING。 还需要注意TERMINATED状态是不可逆的,一旦线程执行完毕,就无法再回到其他状态。另外,中断机制也是状态转换的一部分,如调用interrupt()方法可能会使线程从等待状态被唤醒,抛出InterruptedException,从而改变状态。 在整理这些信息时,要确保逻辑连贯,每个状态的转换条件和触发方法都解释清楚。可能需要画一个转换图来辅助说明,但用户要求用文字描述,所以需要用段落分点说明。同时,要引用正确的来源,比如引用[3]中的测试代码展示了NEW和TERMINATED的状态变化,引用[4]中的中断例子说明了中断对线程状态的影响。 最后,用户要求生成相关问题,我需要根据解释的内容,提出几个相关的扩展问题,帮助用户进一步理解线程状态转换的机制,比如状态转换的条件、中断的作用、不同状态之间的区别等。 现在把这些点组织成结构化的回答,确保每个部分清晰,引用正确,并符合格式要求,比如使用中文,数学公式用$...$,独立公式用$$...$$,但这里可能不需要数学公式。重点放在状态转换的解释和引用对应的内容。</think>### Java线程状态转换图及机制解释 Java线程状态定义在$Thread.State$枚举类中,包括以下六种状态[^2]: 1. **NEW(新建状态)** 线程被创建但未调用$start()$方法时的状态。例如: ```java Thread thread = new Thread(); // 此时状态为NEW ``` 2. **RUNNABLE(可运行/运行状态)** 调用$start()$后,线程进入RUNNABLE状态。此状态实际包含操作系统中的**Ready(就绪)**和**Running(运行中)**两种子状态[^1]。是否真正运行取决于CPU时间片的分配。 3. **BLOCKED(阻塞状态)** 线程因等待进入同步代码块(如`synchronized`锁)而阻塞时的状态。例如: ```java synchronized (lock) { ... } // 其他线程等待锁时进入BLOCKED ``` 4. **WAITING(无限等待状态)** 通过调用$Object.wait()$、$Thread.join()$或$LockSupport.park()$等方法进入的**无超时限制**的等待状态。 5. **TIMED_WAITING(时限等待状态)** 通过调用$Thread.sleep(long n)$、$Object.wait(long timeout)$等方法进入的**有超时限制**的等待状态[^5]。 6. **TERMINATED(终止状态)** 线程执行完$run()$方法后的最终状态,不可逆[^3]。 --- ### 状态转换机制 #### 1. **基础转换路径** - **NEW → RUNNABLE**:调用$start()$方法后转换。 - **RUNNABLE → TERMINATED**:线程正常执行结束或抛出未捕获异常。 - **RUNNABLE ↔ BLOCKED**:因锁竞争进入BLOCKED,获取锁后回到RUNNABLE。 #### 2. **等待状态转换** - **RUNNABLE → WAITING** 调用$Object.wait()$(需其他线程调用$notify()$唤醒)或$Thread.join()$(等待目标线程终止)。 - **RUNNABLE → TIMED_WAITING** 调用带超时的方法如$Thread.sleep(1000)$或$Object.wait(5000)$。 #### 3. **中断恢复** - **WAITING/TIMED_WAITING → RUNNABLE** 通过其他线程调用$interrupt()$触发中断,线程抛出$InterruptedException$并恢复运行[^4]。 - **BLOCKED → RUNNABLE** 当锁可用时,线程重新竞争锁成功。 --- ### 转换示意图(文字描述) ``` NEW → start() → RUNNABLE ↓ TERMINATED(执行结束) ↓ RUNNABLE → synchronized锁竞争失败 → BLOCKED ↓ RUNNABLE → wait()/join() → WAITING ↓ RUNNABLE → sleep(n)/wait(n) → TIMED_WAITING ``` --- ### 关键注意事项 1. **RUNNABLE状态的实际含义** 操作系统可能未分配CPU时间片,此时线程处于Ready子状态。 2. **中断机制** 调用$interrupt()$会中断WAITING/TIMED_WAITING状态,但不会直接终止线程[^4]。 3. **状态不可逆性** TERMINATED是最终状态,无法通过任何方法回到其他状态[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值