Java 中的线程有如下六种状态:
- 新建(New): 当线程对象被创建后,它就处于新建状态。在这个状态下,线程还未开始执行。
- 可运行(Runnable): 调用线程的
start()
后,线程就进入可运行状态。- 在这个状态下,线程可能正在运行,这时线程是运行中(Running)
- 也可能正在等待系统为其分配处理器资源,这时线程是就绪(Ready)
- 阻塞(Blocked): 当线程试图获取一个锁(synchronized资源)而该锁被其他线程持有时,则该线程进入阻塞状态。线程会在这个状态下等待,直到它可以获取到锁。
- 等待(Waiting): 当线程等待其他线程完成特定操作时,它会进入等待状态。例如,当线程调用
Object.wait()
、Thread.join()
或LockSupport.park()
时,它会进入这个状态。 - 超时等待(Timed Waiting): 这个状态与等待状态类似,但有时间限制。例如,当线程调用
Thread.sleep(long millis)
、Object.wait(long timeout)
、Thread.join(long millis)
或LockSupport.parkNanos()/parkUntil()
时,它会进入定时等待状态。 - 终止(Terminated): 当线程的
run()
方法执行完成后,它会进入终止状态。这意味着线程的任务已经结束了。
状态转换
几个方法的比较
Thread.sleep(long millis)
:当前线程调用该方法后,线程进入超时等(TIMED_WAITING
)状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态(Ready
)。注意,该方法不会释放任何监视器(锁),如果一个线程持有锁,当它调用sleep()
方法时,它仍然会保持对这些锁的持有。这意味着其他需要这些锁的线程可能会被阻塞,直到该线程醒来并释放锁。Thread.yield()
:当前线程调用该方法后,线程会放弃获取的CPU时间片,但不释放锁资源,线程由运行状态(Running
)变为就绪状态(Ready
),让操作系统再次选择线程。它的作用是使当前正在执行的线程暂停执行,给其他同等优先级的线程执行的机会,但并不保证一定会轮流执行,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()
不会导致阻塞。该方法与sleep()
类似,只是不能由用户指定暂停多长时间Thread.join()/Thread.join(long millis)
:当前线程里调用其它线程T
的join()
,当前线程进入WAITING/TIMED_WAITING
状态,当前线程不会释放已经持有的对象锁。线程T
执行完毕或者millis
时间到,当前线程一般情况下进入RUNNABLE
状态,也有可能进入BLOCKED
状态(因为join是基于wait实现的)。Object.wait()
:当前线程调用对象的wait()
方法,当前线程释放对象锁,进入等待队列。依靠notify()
/notifyAll()
唤醒或者wait(long timeout)
timeout时间到自动唤醒。需要注意的是Object.wait()
必须要在同步代码块或同步方法中调用,这意味着调用它的线程必须持有该对象的监视器锁。当一个线程调用wait()
时,它会释放持有的监视器锁并进入等待状态,则其他线程就可以获取锁并执行同步的代码块或方法。Object.notify()
:当一个线程调用notify()
时,它会从这个对象的等待池中随机唤醒一个正在执行wait()
方法的线程。被唤醒的线程会尝试重新获得监视器锁。一旦获得锁,它就可以继续执行。notifyAll()
唤醒是在此对象监视器上等待的所有线程。与wait()
方法一样,notify()
也必须在同步代码块或同步方法中调用LockSupport.park()/LockSupport.parkNanos(long nanos),LockSupport.parkUntil(long deadlines)
:该类方法用于阻塞当前线程,直到获得许可(permit)或者线程被中断。调用这类方法的线程进入WAITING/TIMED_WAITING
状态。可以通过LockSupport.unpark(Thread thread)
方法被唤醒。LockSupport
使用一种许可(permit)机制。每个线程都有一个与之关联的许可,许可不能累积,它的数量只能是 0 或 1。- 如果一个线程已经拥有许可,那么
park()
方法将立即返回,然后消耗这个许可。如果没有许可,park()
会阻塞线程。 - 当调用
unpark()
时,会给指定线程发放一个许可(如果它之前没有许可的话),从而使得被park()
阻塞的线程返回。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。