- 概述
当线程被创建并启动之后,它即不是已启动就进入到了执行状态,也不是一直处于执行状态。在线程的生命周期中有6种状态
在JavaAPI帮助文档中java.lang.Thread.State
这个枚举给出了线程的6种状态。
线程状态 | 导致状态发生条件 |
---|---|
NEW新建 | 线程刚被创建,但是还没有启动,还没有调用start方法 |
RUNNABLE(可运行) | 线程可以在java虚拟机中运行的状态,可以是正在运行自己的代码,也可能没有,这取决于操作系统处理器 |
BLOCKED(锁阻塞) | 当一个线程试图获取一个对象锁,而该对象锁被其他线程所持有,则该线程进入到Blocked状态;当该线程持有锁时,该线程就进入到Runnable状态 |
WAITING(无限等待) | 一个线程在等待另一个线程执行一个动作(新建)时,该线程就进入到Waiting状态,进入这个Waiting状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒 |
TIMED_WAITING(计时等待) | 同Waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态,这一状态将一直保持到超时期满或者是收到了唤醒通知。带有超时参数的常用方法有Thread.sleep(),Object.wait(). |
TERMINATED (被终止) | 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。 |
- 六种状态切换描述:
Timed Wating(计时等待)
Timed Wating 在javaAPI中描述为:一个正在限时等待另一个线程执行一个(唤醒)动作的线程处于这一状态
其实当我们调用了slee方法之后,当前正在执行的线程就进入到了计时等待状态。
练习:实现一个计数器,计数到100,在每个数字之间暂停1秒,每隔10个数字输出一个字符串。
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 1;i <= 100 ; i ++) {
if (i % 10 == 0) {
System.out.println("------------------>" + i);
}
System.out.println(i);
// 在每个数字之间暂停1秒
try{
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 准备一个main函数
public static void main(String[] args) {
new MyThread().start();
}
}
备注:
1. 进入到Timed Waiting状态的一种常见的操作是调用sleep方法,单独的线程也可以调用,不一定非要有协作关系
2. 为了让其它线程有机会执行到,一般建议将Thread.sleep()调用放到线程run方法内,这样才能保证该线程执行过程中会睡眠
3. sleep与锁无关,线程睡眠到期会自动苏醒,并返回到Runnable状态。sleep()里面的参数指定的时间是线程不会运行的最短是时间,因此,sleep()方法不能保证该线程睡眠到期后就会立刻开始执行
Blocked所阻塞状态
Blocked状态在javaAPI中描述为:一个正在阻塞等待一个监视器锁(锁住对象)的线程处于这一状态
比如:线程A与线程B代码中使用同意把锁,如果线程A获取到锁对象,线程A就进入Runnable状态,反之线程B就进入到Blocked所阻塞状态
waiting无限等待状态
Waiting状态在javaAPI中的描述:一个正在无限等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态
一个调用了某个对象的Object.Wait()方法的线程,会等待另一个线程调用此对象的Object.notify()或者Object.notifyAll()方法
其实waiting状态他并不是一个线程的在操作,它体现的是多个线程之间的通信,可以理解为多个线程之间的协作关系,多个线程会争取锁,同时相互之间又存在协作关系