本文主要介绍了线程的状态图,以及通过iOS中NSThead的具体例子来详细解释每个状态的意义。
- 线程状态图综述
- JAVA中线程状态图实例
- iOS中NSThead线程状态图
线程状态图综述
新建状态(New) : 线程对象被创建后,就进入了新建状态。
就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程
运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
阻塞状态(Blocked) : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
等待阻塞 – 通过调用线程的wait()方法,让线程等待某工作的完成。
同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。死亡状态(Dead) : 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
下面通过一个更具体的运行图来再次解释线程的各个状态
JAVA中线程状态图实例
详细解释三种阻塞状态
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
补充:
Synchronized是非公平锁。 Synchronized在进入等待列表时,等待的线程会先尝试自旋获取锁,如果获取不到就进入等待列表,这明显对于已经进入队列的线程是不公平的。
iOS中NSThead线程状态图
下面是iOS中NSThead的使用详解
新建状态 : 实例化线程对象
1 | 说明:创建线程有多种方式,这里不做过多的介绍 |
就绪状态 :向线程对象发送 start 消息,detachNewThreadSelector 方法和 performSelectorInBackground 方法会直接实例化一个线程对象并加入可调度线程池
1 | 线程开启 : 线程进入可调度线程池 |
运行状态:
- CPU 负责调度可调度线程池中线程的执行
- 线程执行完成之前(死亡之前),状态可能会在就绪和运行之间来回切换
- 就绪和运行之间的状态变化由 CPU 负责,程序员不能干预
- 当 CPU 调度当前线程 , 进入运行状态
- 当 CPU 调度其他线程 , 进入就绪状态
阻塞状态 : 当满足某个预定条件时,可以使用休眠或锁阻塞线程执行
1 | 方法执行过程,符合某一条件时,可以利用 sleep 方法让线程进入 阻塞 状态 |
死亡状态: (一旦线程停止或死亡了,就不能再次开启任务 , 后续的所有代码都不会被执行 )
1 | (1) 正常死亡 |
1 | (2) 非正常死亡 |
内存情况 : 线程死亡后,线程对象从内存中移除