Java随笔-线程生命周期
状态
以JDK16为例,线程有6种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
-
NEW 初始状态,创建了线程,但还没有调用start()。 RUNNABLE 可运行状态、或就绪状态,可以细分为运行(running)和就绪(ready)两种状态,获得了CPU使用权,就进入运行状态,失去了CPU使用权就进入就绪状态,只有就绪状态才能进入运行状态。 BLOCKED 阻塞状态,让出CPU使用权,中断本线程执行。 WAITING 等待状态。 TIMED_WAITING 限时等待状态。 TERMINATED 终止状态。
生命周期
线程不同状态之间的转换不仅仅只有上图中几种方式,可能还有其他的方式,上图中只是显示了常见的几种方式。
NEW与RUNNABLE
-
创建Thread扩展类对象,并重写run(),调用start(),线程状态由NEW转为RUNNABLE。 实现Runnable接口,重写run(),调用start(),线程状态由NEW转为RUNNABLE。
RUNNABLE与WAITING
-
当线程获得synchronized 隐式锁,调用无参的wait()方法时,此时由RUNNABLE转换为WAITING。 当线程调用无参join()方法时,此时等待的线程会由RUNNABLE转变为WAITING,当线程执行完后,等待的线程由WAITING转为RUNNABLE。 当调用 LockSupport.park() 时,线程会由RUNNABLE转变为WAITING,当调用 LockSupport.unpark(Thread thread)时,线程由WAITING转为RUNNABLE。LockSupport.park() 与LockSupport.unpark(Thread thread)用于Java并发锁。 当调用notify()或notifyAll()时,线程会被唤醒,线程状态WAITING转变为RUNNABLE。
RUNNABLE与TIMED_WAITING
-
当调用Thread.sleep(long millis) ,线程状态由RUNNABLE转为TIMED_WAITING。 当获得synchronized 隐式锁,且调用wait(long timeout),线程状态由RUNNABLE转为TIMED_WAITING。 当调用Thread.join(long millis)时,线程状态RUNNABLE转为TIMED_WAITING。 当调用 LockSupport.parkNanos(Object blocker, long deadline) 时,线程会由RUNNABLE转变为TIMED_WAITING 。 当调用 LockSupport.parkUntil(long deadline)时,线程会由RUNNABLE转变为TIMED_WAITING 。 当调用notify()或notifyAll()时,线程会被唤醒,线程状态TIMED_WAITING 转变为RUNNABLE。 当调用 LockSupport.unpark(Thread thread)时,线程由TIMED_WAITING 转为RUNNABLE。
RUNNABLE与BLOCKED
-
当调用sleep(),wait(),suspend(),等待I/O时,线程其实在等待synchronized 隐式锁,此时线程状态会由RUNNABLE转为BLOCKED 。
WAITING、TIMED_WAITING 、BLOCKED
-
WAITING与TIMED_WAITING 差不多,当调用的方法中有时间参数,进入的状态就会是TIMED_WAITING ,否则就是WAITING。 BLOCKED是在等待其他线程释放monitor锁,而WAITING和TIMED_WAITING则是等待其他线程执行完毕。
总结
-
一个线程只能一次NEW和TERMINATED,也就是,。 线程可由NEW进入RUNNABLE,反之不可,其他状态也如上图,线程生命周期不可逆。