线程执行过程中的状态
1 线程执行过程中的状态
- new 初始化状态
- runnalbe 可运行/运行状态
- blocked 阻塞状态
- waiting 等待状态,无时间限制
- timed_waiting 超时等待,有时间限制
- terminated 终止状态
1.1 各个状态介绍
1.1.1 new 初始化状态
实现Runnable接口和继承Thread可以得到一个线程类,从而可以new一个实例出来,线程进入初始化。
public class ThreadTest extends Thread{
private String name;
public ThreadTest(String name){this.name = name}
public void run(){
for(int i = 1; i < 11; i++){
System.out.println(Thread.currentThread().getName() + " Thread " + i);
}
}
public static void main(String[] args){
ThreadTest t1 = new ThreadTest("thread1");
ThreadTest t2 = new ThreadTest("thread2");
ThreadTest t3 = new ThreadTest("thread3");
t1.start();
t2.start();
t3.start();
}
}
public class TestRunnable implements Runnable{
public void run(){
for(int i = 1; i < 11; i++){
System.out.println(Thread.currentThread().getName() + " Thread " + i);
}
}
public static void main(String[] args){
ThreadTest t1 = new ThreadTest("thread1");
ThreadTest t2 = new ThreadTest("thread2");
ThreadTest t3 = new ThreadTest("thread3");
t1.start();
t2.start();
t3.start();
}
}
1.1.2 Runnable 就绪,运行中的状态
- 就绪状态只是说你自己在运行,调度程序没有选到你,你就永远是就绪状态。
- 调用线程的start()方法,线程进入就绪状态
- 当前线程slee()方法结束,其他进程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。
- 当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。
- 锁池里的线程拿到对象锁后,进入就绪状态。
1.1.3 Running 运行中状态
线程调度程序可以从运行池中选择一个线程作为当前线程时,线程进入运行状态。
这也是线程进入运行状态的唯一方式。
1.1.4 Blocked 阻塞状态
阻塞状态是指线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)之前的状态。
1.1.5 Waiting 等待状态
调用sleep()或者wait()方法后,线程处于waiting状态,等待被唤醒。
1.1.6 timed_waiting 等待超时状态
调用sleep()或者wait()方法后,线程处于timed_waiting状态,等待被唤醒,或者超时被自动唤醒。
1.1.7 treminated 终止状态
- 当前线程的run方法完成时,或者主线程的main方法完成时,我们就认为他终止了。这个对象也许是活的,但是他已经不是一个独立执行的线程。线程一旦停止,就不能复生。
- 在一个终止线程上调用start方法,会抛出java.long.IllegalThreadStateException异常
1.2 线程之间状态的切换
1.2.1 new -> runnable
- 实现runnable接口,或者集成thread类,可以获得一个线程类,创建这个类的实例对象,就是new
- new状态的线程不会被操作系统调度,也不会被执行
- 调用的这个线程的start方法,将new状态转换成runnable状态
1.2.2 runnable -> block -> runnable
- runnable线程获得cpu运行时间,执行run方法,进入running状态
- running线程进入synchronized同步块,可能进行同步阻塞或IO阻塞,进入blocked状态
- block线程同步synchronized同步块,可能进行同步块释放或IO完成,进入runnable状态
只有当线程等待synchronized的隐形锁时,线程才会从runnable向blocked状态转换。
被synchronizded关键字修饰的方法、代码,在同一时刻,只允许一个线程运行。
所以在这种情况下,等待的线程就会从runnable变为block,当等待的线程获得synchronized隐式锁时,就会从block状态转到如runnable。
1.2.3 runnable -> running -> waiting -> runnable
- 有三种情况会触发线程从runnable转到waiting
- 获得synchronized的线程调用Object.wait()
- 调用线程同步Thread.join方法
- 线程A在runnable。得到cpu执行时间后,变为running
- 线程B调用join方法,插队。
- 线程A进入主动等待状态,变为waiting
- 线程B执行完毕了以后,线程A变为runnable
- 调用LockSupport.park方法。Java并发包中的锁,都是基于LockSupport对象实现的。
- 调用LockSupport.park(),线程会阻塞,从running变为waiting
- 调用LockSupport.unpark(),线程被唤醒,从waiting变为runnable
1.2.4 runnable -> timed_waiting
- 有五种情况会出发线程从runnable转到timed_waiting
- 调用带超时参数的Thread.sleep(long millis)
- 获得synchronized线程,调用带参数的OBject.wait(long deadline)方法
- 调用带参数的LockSupport.parkNanos(Object blocker, long deadline)
- 调用带超时参数的LocalSupport.parkUntil(long deadline)
1.2.5 runnable -> terminated
这是一个自动的过程,一个线程正常运行完毕以后,就会变成terminated
如果运行时,有异常抛出,也会终止进程
或者调用interrupt方法,中断线程。