下次面试再一上来就问我线程有哪些状态,我上去就是给他一 jio

是的,今天必须要把它给彻底根治了!

现在 Java 面试,基本上都会问到多线程,那么随之而来的线程状态,很多时候都会被问到,大部分人都知道线程的几种状态,但是让你整体全部串起来,做到面试时游刃有余,估计很多人记忆不是很清晰。

今天武哥就把这些全部给整了,下次面试官再问,就把这篇文章扔给他。

1. 开局一张图,其他全靠吹

本文的核心就在于这幅图。我用 PPT 画了好几个小时,应该是全网最清新最好看的一张图了吧(不接受反驳,谁反驳上去也是一jio,手动滑稽)

好了,牛逼不能再吹了,我们根据上面这幅图来展开,我把这块涉及到的东西都跟大家理一遍,希望看过这篇文章的小伙伴,特别是初学者,后面不用再在这个问题上纠结了。

针对线程的状态,首先来看下官方的源码(除去了注释):

public enum State {
	NEW,
	RUNNABLE,
	BLOCKED,
	WAITING,
	TIMED_WAITING,
	TERMINATED;
}

所以从官方的角度,线程是有6种状态的,结合官方的注释,我首先把六种状态解释一下,然后具体讲解一下每个状态之间转换所涉及到的那些方法。把这些都理清楚了,这一块也就差不多了。

2. 线程的6种状态解释

结合上面的那张图一起看:

NEW:线程被创建出来了,但是还没有start()。

RUNNABLE:可运行状态,这个状态比较特殊,我在图中把这个状态拆分成了两部分:一部分是READY,顾名思义是准备状态,另一部分是RUNNING,即运行状态。

准备状态:只能说明你有资格运行,但只要调度程序没有调度到你,你就永远是准备状态。从图中可以看出,好几个状态都能切换到准备状态,至于切换的方法,我在下文详细给大家整理出来介绍。

运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。说白了,就是线程跑起来了。

BLOCKED:阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。

WAITING:等待状态的线程不会被分配 CPU 执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。

TIMED_WAITING:超时等待状态的线程不会被分配 CPU 执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。这是和上面的 WAITING 状态的区别。

TERMINATED:终止状态,顾名思义,线程执行结束了。

3. 线程状态之间的切换函数分析

从上面的图中可以看出,线程之间的状态切换,主要涉及到以下几个函数:

Thread.sleep、Thread.yeild、Object.wait、Thread.join、Object.notify/notifyAll、
LockSupport.park/unpark/parkNanos/parkUtil

接下来针对这几个函数,做一下简单的功能分析和对比,大家可以结合上面的那幅图。

Thread.sleep(time):当前线程调用此方法,顾名思义,就是让当前线程进入 TIMED_WAITING 状态,睡眠固定的时间(但是不释放对象锁),到点后自动唤醒,进入准备状态。主要作用是给其他线程执行机会。

Thread.yield():当前线程调用此方法,放弃获取的CPU时间片,但不释放锁资源,由运行状态变为准备状态,让OS再次选择线程。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。它跟 sleep方法的区别在于不能指定暂停多少时间。

Object.wait():当前线程调用对象的wait()方法,当前线程释放对象锁,进入WAITING 状态。依靠notify()/notifyAll()来唤醒;而wait(time)方法的主要区别是进入 TIMED_WAITING 状态,到达时间后,自动唤醒。

Object.notify/notifyAll:notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。

Thread.join():当前线程里调用其它线程 t 的join()方法,当前线程进入 WAITING 状态,当前线程不会释放已经持有的对象锁。线程 t 执行完毕,当前线程进入 RUNNABLE 状态。而join(time)方法的主要区别是当前线程进入 TIMED_WAITING 状态,到达时间后,进入 RUNNABLE 状态。

LockSupport.park():当前线程进入 WAITING 状态,需要通过LockSupport.unpark(thread)来唤醒。

LockSupport.parkNanos(nanos)/parkUntil(deadlines):当前线程进入 TIMED_WAITING 状态,需要通过``LockSupport.unpark(thread)`来唤醒。

相比于wait方法,LockSupport不需要获得锁就可以让线程进入 WAITING 或者 TIMED_WAITING 状态。

当然了,还有个 BLOCKED 状态,涉及到 synchronized关键字,由于这块也是面试经常会问到的,下一篇我会全面剖析一下synchronized。

关于线程的状态以及状态间切换所涉及到的函数,这篇文章就总结这么多。全篇围绕文章开头的那幅图,我觉得这块内容,只要把那幅图记住,就基本没什么问题了。如有疑问,欢迎讨论。

Java多线程并发核心面试题

  • JAVA 并发知识库
  • JAVA 线程实现/创建方式
  • 4 种线程池
  • 线程生命周期(状态)
  • 终止线程 4 种方式
  • sleep 与 wait 区别
  • start 与 run 区别
  • JAVA 后台线程
  • JAVA 锁
  • 线程基本方法
  • 同步锁与死锁
  • 线程上下文切换
  • 线程池原理
  • Java阻塞队列原理
  • CyclicBarrier、CountDownLatch、Semaphore 的用法
  • volatile 关键字的作用(变量可见性、禁止重排序)
  • 如何在两个线程之间共享数据
  • ThreadLocal 作用(线程本地存储)
  • synchronized 和 ReentrantLock 的区别
  • ConcurrentHashMap 并发
  • Java 中用到的线程调度
  • 进程调度算法
  • 什么是 CAS(比较并交换-乐观锁机制-锁自旋)
  • 什么是 AQS(抽象的队列同步器)

详细内容

由于内容篇幅较多,博主偷个懒,截几张内容图,已经分类整理成PDF文档,如需要这些可转发+关注后扣【多线程】获取!

这些PDF博主已经整理好了,需要免费领取的朋友麻烦转发博主这篇文章,然后扣【多线程】免费领取!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值