先声明一下水印问题,一开始公众号是叫午茶电影,后面我又改了个名字,但是在写这篇文章的时候,还是原来那个名字,这绝对不是转载的,因为你搜 wuchastory 公众号,就能搜到我这个。
线程大家都有在使用,但是有时候也仅仅是使用,对它的一些行为还不是特别的了解,今天就来和大家谈谈线程的状态这个内容。
首先线程有哪些状态呢?
这个问题,我们可以从 Java 的源代码中找到的答案,先简单粗暴,直接贴上代码,看看线程的状态有哪些:
看完了,大家也知道了,线程有 6 个状态。
这 6 个状态分别是:New, Runnable, Blocked, Waiting, Timed_Waiting, Terminated.
分别是什么意思呢?咱们一一来解释,其实说起来也简单。
New:这个状态呢,就是线程对象创建之后、启动之前,就是这个状态。
用代码来说呢,就是
这个 New 状态很好理解。
Runnable: 当调用 start 方法后呢,线程就会进入 Runnable 状态,表示,我这个线程可以被执行了,如果调度器给这个线程分配了 CPU 时间,那么这个线程就可以被执行,这里一定要正确区分一下 Runnable 不是说正在执行,而是可以被执行,这两个还是有区别的。
Blocked: 这个状态,当线程要进入临界区的时候,会发生。比如说,前面有一个临界区的代码需要执行,那么线程就会进入这个状态,如果只有一个线程呢,那么也就只有它一个在进入临界区了,它就会进入临界区开始执行,随后转为 Runnable 状态。如果有多个线程到了临界区,那么都会进入 Blocked 状态,由调度器选一个来执行,如果这个线程执行完毕后,大家还是一同为 Blocked 状态,调度器再选一个来执行。
所以很有可能发生的情况是,选了 A 线程执行,BCD 都在等着,A 执行完了后,还是偏心的选了 A 线程执行。
Waiting: waiting 状态,当你调用了 wait,join 方法后,就会进入这个状态。一旦进入到这个状态,CPU 就不会管你了,直到有别的线程通过 notify 方法将它唤起,否则的话,就会一直在等待中。设计这个状态怎么用呢?我的理解是,线程 A 需要完成一些事情,但是这些事情必须要满足某些条件才能继续,因此,如果我写一个死循环在这里等待,就很优雅了(浪费 CPU 资源),这时就可以使用这个 waiting 状态,条件未满足前,我进入 waiting 状态,等条件满足了,别人来通知我,我在继续执行。
Timed_Waiting: 这个状态也是等待,但是是有一个计时器在里面,最常见的是使用 Thread.sleep 方法触发,触发后,线程就进入了 Timed_waiting 状态,随后会由计时器触发,再进入 Runnable 状态。
Terminated: 终结状态,当线程的所有代码都被执行完毕后,会进入到这个状态,这个就是字面意思了。
总的来说,状态切换如下图所示了:
可见,几个重要状态的切换都是从 Runnable 转换出去,再转换回来的
然而……
咱们还是得实践一把,才能整明白啊,光纸上谈兵咋行呢。于是我就凭空捏造了一个需求:
有一个 4 *50 的二维数组,用 4 个线程去分 5 个阶段去填满它,也就说,第一阶段大家一起填 0 -9,当大家都填满了 0 -9,再一起去填 10-19,以此类推,先填满的线程要等着其他线程都填好了,再继续。
这样就能看到 4 个线程争先恐后的填数组,跑得快的还得先等着跑得慢的,然后大家再继续跑第二阶段。
这里直接放上效果图(下面是 GIF,会动的):
代码放在 github 上了,如需自取:https://github.com/krossford/…
如果大家喜欢我的文章,请关注我新开的公众号:好奇码农君
微信公众号:好奇码农君