一文详解Java线程的6种状态与生命周期
线程生命周期
Java线程的生命周期可以分为6种不同的状态:
1. New(新建): 当线程对象被创建时,它处于新建状态,但还没有开始运行。
2. Runnable(可运行): 当调用start()方法时,线程进入可运行状态,等待被线程调度器分派时间片得以运行。
3. Blocked(阻塞): 线程被阻塞于某一个等待状态,如等待一个I/O操作的完成或等待获取一个锁。
4. Waiting(等待): 线程处于一个无限期的等待状态,直到线程被特定的notify()或notifyAll()方法唤醒。
5. Timed Waiting(超时等待): 线程等待一个指定的时间,在等待的时间到达之前可以通过notify()或notifyAll()方法唤醒。
6. Terminated(终止): 线程已经执行完毕或发生了一个异常而终止。
线程状态转换
Java线程的状态可以不断地改变,具体状态转换如下:
- New -> Runnable:当调用了线程对象的start()方法时,线程进入可运行状态,等待系统的线程调度器来调度该线程执行。
- Runnable -> Running:当线程被分配到CPU时间片后,线程开始执行run()方法,进入Running状态。
- Running -> Runnable:当线程在执行时,遇到了某个条件(如睡眠时间结束、I/O完成、wait()被notify()方法唤醒)无法继续执行时,线程自动切换成可运行状态。
- Running -> Blocked:当线程试图获取一个被其他线程持有的锁或者在等待某个输入/输出操作完成时,该线程会进入阻塞状态(Blocked)。
- Blocked -> Runnable:当线程持有锁的同时,马上就会调用synchronized方法/块(等待另外一个信号),该线程会进入阻塞状态(Blocked),等待另外一个信号。
- Running -> Waiting:线程执行wait()方法,处于 Waiting 状态,在被notify() 方法唤醒之前等待状态不会被改变。
- Waiting -> Runnable:线程被notify()方法唤醒,进入 Runnable 状态。
- Running -> Timed Waiting:线程执行sleep()方法或wait(long)方法,进入Timed Waiting状态,知道超时或被唤醒。
- Timed Waiting -> Runnable:线程等待超时或被唤醒,回归Runnable状态。
- 任何状态 -> Terminated:当线程执行完毕(run()方法完成),或者因为异常退出时,该线程被置于终止状态(Terminated)。
示例说明
示例1:线程阻塞
public class ThreadBlockTest {
public static void main(String[] args) {
Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
System.out.println("t1获取到锁,开始执行;");
try {
lock.wait(); // 使当前线程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1被唤醒了,重新获取锁,继续执行");
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
System.out.println("t2获取到锁,开始执行;");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notify(); // 唤醒正在等待的线程
System.out.println("t2执行完成,释放锁");
}
}
});
t1.start();
t2.start();
}
}
以上代码中,我们创建了两个线程t1和t2,t1运行后,调用lock.wait()方法使自己处于阻塞状态,等待被唤醒。t2获得锁之后,先延时2秒钟,然后调用lock.notify()方法,唤醒正在等待的线程t1,使其从wait()方法阻塞的状态恢复到Runnable状态。
示例2:线程等待
public class ThreadWaitTest {
public static void main(String[] args) {
Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
System.out.println("t1获取到锁,开始执行");
try {
lock.wait(5000); // 使当前线程进入等待状态,超时时间为5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1被唤醒了,重新获取锁,继续执行");
}
}
});
t1.start();
}
}
以上代码中,我们创建一个线程t1,在synchronized(lock)代码块中,调用lock.wait(5000)方法,使当前线程进入超时等待状态,等待5秒钟。5秒钟后,如果没有其他线程调用lock.notify()方法来唤醒当前线程,则t1从Timed Waiting状态转换为Runnable状态,继续执行。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文详解Java线程的6种状态与生命周期 - Python技术站