1.创建状态:NEW

        线程刚被创建出来,但还没调用 start() 方法。就像是安排了任务但是还没有开始行动。这里的线程状态就是NEW,这里的线程因为没有给他起名字所以是系统设置的Thread-0,

2.运行状态:RUNNABLE

        调用 start() 方法后进入的状态,它包含了两种表示方式:1.正在再CPU上运行;2.线程已经准备就绪了,随时可以再CPU上运行。

3.等待状态

        这里的等待状态有三种,WAITING(等待),TIMED_WAITING(超时等待),BLOCKED(阻塞)。

WAITING

        这种状态是属于无限等待,线程会无限期等待另一个线程,在下图代码中为了得到这个WAITING状态,使用了wait()方法,这个方法要与synchronized方法配合使用,而且又没有用notify()方法,将该线程唤醒所以使得线程处于无限等待状态。

TIMED_WAITING

        超时等待它与上面的无限等待的区别在于,它可以设置一个时间段,当过了这个时间段,该线程会被自动唤醒。

在下面代码中使用了sleep()方法(也可以用Thread.sleep(long)Object.wait(long)Thread.join(long)),让线程等待了10s,在这个过程中这个线程就是TIMED_WAITING状态,10s之后程序运行完成。

BLOCKED

        这种状态是线程是因为竞争 synchronized 锁产生的阻塞状态下面的代码中这两个线程就产生了死锁t1线程拿了锁A,之后又想拿锁B,t2线程拿了锁B,之后又想拿锁A,互相等待对方释放锁的场景,满足死锁的四大条件(1.锁互斥,2.不可被剥夺,3.请求并保持,4.循环等待)。

4.终止状态

        线程的 run () 方法执行完毕,或者因异常退出了 run () 方法,使得线程生命周期结束。下面代码使用了sleep()方法让main线程等待,使得t1线程有足够的时间执行结束

想看每一个线程的运行状态还可以使用jconsole工具,他是在你所安装的JDK的bin目录下,如果打开发现没有本地进程可以右键点击管理员权限打开

5.状态之间的切换条件

1.NEW → RUNNABLE

切换条件:调用线程对象的 start() 方法 。新建的线程(NEW 状态)调用 start() 后,就具备上 CPU 执行的资格,进入 RUNNABLE 状态 。

2.RUNNABLE → BLOCKED

切换条件:线程竞争 synchronized 修饰的同步代码块 / 方法时,锁被其他线程占用 。

3.RUNNABLE → WAITING

切换条件:调用以下方法时,线程主动进入无限期等待。

例如:Object.wait()需在 synchronized 代码块 / 方法内,调用后释放锁 ,等待其他线程用 notify()/notifyAll() 唤醒。

Thread.join()调用其他线程的 join 方法,当前线程等被 join 线程结束 。

4.RUNNABLE → TIMED_WAITING

切换条件:调用带超时参数的方法,线程进入计时等待,超时或被唤醒后回到 RUNNABLE 。

Thread.sleep() ,线程休眠指定毫秒数,期间放弃 CPU。

Object.wait() ,在同步代码块内调用,等待指定时间,没被唤醒到时间也会醒。

Thread.join() ,最多等被 join 线程 millis 毫秒。

5.WAITING/TIMED_WAITING → RUNNABLE

WAITING 唤醒条件:Object.wait() 进入,其他线程调用同一对象的 notify()/notifyAll() ,且当前线程竞争到锁,回到 RUNNABLEThread.join() 进入,被 join 线程执行完(TERMINATED),当前线程回到 RUNNABLE。

TIMED_WAITING 唤醒条件:使用notify()/notifyAll()方法,超时时间到 也会自动回到 RUNNABLE 。

6.RUNNABLE → TERMINATED

切换条件:线程的 run() 方法正常执行完毕,或者因未捕获异常退出 run() 方法 。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐