JAVA进阶系列 - 并发编程 - 第3篇 线程的生命周期
2021-01-15 03:14
标签:将不 print 类对象 方法 pre 指定 ace 概念 表示 线程的生命周期 线程的状态定义 线程的状态转移 上一篇文章中,我们简单的描述了同步与异步的差异以及线程的基本使用。那么今天我们就来了解一下线程的生命周期。 在调用了 Thread 类对象的 start 方法来启动 Java 线程后,对应的底层操作系统线程不能马上得到 CPU 时间片来执行,需要等待操作系统的调度。所以,为了便于跟踪 Java 线程的执行情况,Thread 类定义了一系列的线程状态来表示当前线程的执行情况,同时整个线程的整个生命周期就是在这些状态直接转换。 为了便于对 Java 的线程进行管理和对线程的运行情况进行跟踪,Java 定义了 6 个线程状态来表示线程的当前运行情况,这6个状态具体在 Thread 类的内部枚举类 State 中定义: 当我们用关键字 new 创建一个 Thread 对象时,因为没有调用 start 方法启动该线程,此时的 Thread 对象就是一个普通的 Java 对象,并不会执行任何操作。 线程通过调用 start 方法启动,使该线程对象进入 RUNNABLE 状态,此时才真正地在 JVM 进程中创建了一个线程。 但是线程启动之后可以立即得到执行吗?答案是否定的。线程的运行与否和进程一样都要听命于 CPU 的调度。如果操作系统的 CPU 此时是空闲的,则该线程对象对应的线程可以立即获取到 CPU 时间片并执行(此时的线程状态为运行中running)。反之,如果此时 CPU 繁忙,不能马上分配 CPU 时间片资源来执行该线程,则该线程需要等待操作系统之后的调度来获得 CPU 时间片并执行(此时的线程状态为就绪ready)。 当线程处于阻塞状态 BLOCKED 时,线程不能继续往下执行。这种情况主要出现在如下几种情况中: 调用了 sleep 或者 wait 方法而加入了 waitSet 中; 进行某个阻塞的 IO 操作; 获取某个锁资源失败从而加入到该锁的阻塞队列中; 线程处于等待状态 WAITING 主要出现在与其他线程进行协作的场景中,具体为当前线程等待其他线程执行某种操作来通知和唤醒当前线程。当前线程处于等待状态 WAITING 时,除了不能继续往下执行外,还有个特性是如果当前线程持有锁,如在 synchronized 方法内或者 synchronized 同步代码块内部执行时,线程进入了等待状态,则会自动释放锁,这样其他线程可以竞争获取该锁。 在 Thread 类的方法设计中,主要是基于 Object 类的 wait、notify 和 notifyAll 方法实现的,其中线程调用 wait 方法时,进入等待状态。另外当线程调用 Thread 类的 join 方法或者调用 LockSupport 的静态 park 方法时,线程也会进入等待状态 WAITING。 超时等待状态 TIMED_WAITING 与等待状态 WAITING 功能类似,不同之处在于 WAITING 状态的等待不支持指定等待时间,没有超时机制,一旦条件不满足就会无限等待下去。而处于超时等待状态 TIMED_WAITING 的线程,指定了最长等待时间,如果超过这个时间条件还未满足,则当前线程会自动唤醒并继续往下执行。 TERMINATED 是一个线程的最终状态。当 Thread 线程对象对应的现场执行完毕时,线程进入终止状态 TERMINATED,在该状态中线程将不会切换到其他任何状态。这意味着该线程整个生命周期都结束了,对应的 Thread 类对象也会被回收销毁。下列这些情况都将会使线程进入 TERMINATED 状态: 线程正常运行结束; 线程意外出错结束; JVM Crash,导致所有线程结束; 图片来源:B站 - 黑马程序员 上图中箭头表示可由该状态向对应状态转换。其中,RUNNABLE 状态涵盖了操作系统层面的 【可运行状态】【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在Java里面无法区分,仍然认为是可运行) 本篇我们学习了线程的生命周期,在使用多线程的过程中,线程的生命周期将会贯穿始终,只有清晰地掌握生命周期各个阶段的切换,才能更好地理解线程的阻塞以及唤醒机制,同时也为掌握同步锁等概念打下一个良好的基础。 今天的文章到这里就结束了,小伙伴们有什么建议或者意见请联系我改进哦,微信公众号:【该昵称无法识别】,你们的支持是我最大的动力!!! JAVA进阶系列 - 并发编程 - 第3篇 线程的生命周期 标签:将不 print 类对象 方法 pre 指定 ace 概念 表示 原文地址:https://www.cnblogs.com/unrecognized/p/14273229.html目标
内容
1. 线程的生命周期说明
2. 线程的状态定义
public enum State {
// 新建状态
NEW,
// 可运行状态
RUNNABLE,
// 阻塞状态
BLOCKED,
// 等待状态
WAITING,
// 超时等待状态
TIMED_WAITING,
// 终止状态
TERMINATED;
}
2.1. 新建状态 NEW
@Slf4j
public class ThreadStateDemo {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
log.debug("running...");
}, "t1");
log.debug("t1 state {}", t1.getState()); // t1 state NEW
}
}
2.2. 可运行状态 RUNNABLE
@Slf4j
public class ThreadStateDemo {
public static void main(String[] args) {
Thread t2 = new Thread(() -> {
while(true){
// runnable
}
}, "t2");
t2.start();
log.debug("t2 state {}", t2.getState()); // t2 state RUNNABLE
}
}
#### 2.3\. 阻塞状态 BLOCKED
@Slf4j
public class ThreadStateDemo {
public static void main(String[] args) {
Thread t5 = new Thread(() -> {
synchronized (ThreadStateDemo.class) {
try {
// time_waiting
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t5");
t5.start();
Thread t3 = new Thread(() -> {
// t5 线程先占用锁,所以该线程会进入 blocked 状态
synchronized (ThreadStateDemo.class) {
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t3");
t3.start();
log.debug("t3 state {}", t3.getState()); // t3 state BLOCKED
}
}
#### 2.4\. 等待状态 WAITING
@Slf4j
public class ThreadStateDemo {
public static void main(String[] args) {
Thread t2 = new Thread(() -> {
while(true){
// runnable
}
}, "t2");
t2.start();
Thread t4 = new Thread(() -> {
try {
// waiting
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t4");
t4.start();
log.debug("t4 state {}", t4.getState()); // t4 state WAITING
}
}
#### 2.5\. 超时等待状态 TIMED_WAITING
@Slf4j
public class ThreadStateDemo {
public static void main(String[] args) {
Thread t5 = new Thread(() -> {
synchronized (ThreadStateDemo.class) {
try {
// time_waiting
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t5");
t5.start();
log.debug("t5 state {}", t5.getState()); // t5 state TIMED_WAITING
}
}
#### 2.6\. 终止状态 TERMINATED
@Slf4j
public class ThreadStateDemo {
public static void main(String[] args) {
Thread t6 = new Thread(() -> {
log.debug("running...");
}, "t6");
t6.start();
try {
// 这里主线程休眠一下,让
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("t6 state {}", t6.getState()); // t6 state TERMINATED
}
}
### 3\. 线程的状态转换
总结
上一篇:Java学习
文章标题:JAVA进阶系列 - 并发编程 - 第3篇 线程的生命周期
文章链接:http://soscw.com/index.php/essay/42071.html