网站首页 > 精选教程 正文
一个线程从创建,到最终的消亡,需要经历多种不同的状态,这些不同的线程状态,由始至终也构成了线程生命周期的不同阶段。
线程的几个重要的状态如下:
* NEW:初始状态,线程被构建,但是还没有调用start方法。
* RUNNABLE:可运行状态,可运行状态包括:运行中状态(RUNNING)和就绪状态(READY)
* BLOCKED:阻塞状态,处于这个状态的线程需要等待其他释放锁或者等待进入synchronized
* WAITING:等待状态,处于该状态的线程需要等待其他线程通知或中断操作,进而进入下一个撞他
* TIMED_WAITING:超时等待状态。可以在一定的时间自行返回
* TERMMINATED:终止状态,当前线程执行完毕
线程的状态转换
代码示例:
创建四个线程timedWaitingThread、waitingThread、blockedThread01、blockedThread02。
* timedWaitingThread线程,在while(true)循环中调用TimeUnit.SECONDS.sleep(long)方法来验证线程的TIMED_WARTING状态。
* waitingThread线程,获取当前类Class对象的synchronized锁,在synchronized中使用线程的wait()方法,来验证线程的WAITING状态,调用wait()方法释放锁。
* blockedThread01线程,获取当前类Class对象的synchronized锁,在while(true)循环中调用TimeUnit.SECONDS.sleep(long),使blockedThread01线程处于TIMED_WARTING状态,并一直持有锁。此时如果调用notify的话,会唤醒waitingThread线程,由于锁被blockedThread01线程抢到并一直占有,waitingThread线程处于BLOCKED(阻塞)状态。
* blockedThread02线程,获取当前类Class对象的synchronized锁,blockedThread02线程尝试获取锁,由于blockedThread01线程抢到锁不释放锁,blockedThread02线程处于BLOCKED(阻塞)状态。
1.timedWaitingThread线程,
在while(true)循环中调用TimeUnit.SECONDS.sleep(long)方法来验证线程的TIMED_WARTING状态。
2.waitingThread线程
获取当前类Class对象的synchronized锁,在synchronized中使用线程的wait()方法,来验证线程的WAITING状态,调用wait()方法释放锁。
3.blockedThread01线程
获取当前类Class对象的synchronized锁,在while(true)循环中调用TimeUnit.SECONDS.sleep(long),使blockedThread01线程处于TIMED_WARTING状态,并一直持有锁。此时如果调用notify的话,会唤醒waitingThread线程,由于锁被blockedThread01线程抢到并一直占有,waitingThread线程处于BLOCKED(阻塞)状态。
4.blockedThread02线程
获取当前类Class对象的synchronized锁,blockedThread02线程尝试获取锁,由于blockedThread01线程抢到锁不释放锁,blockedThread02线程处于BLOCKED(阻塞)状态。
5.运行线程
6.以直接点击IDEA下图所示的图表直接打印出线程的堆栈信息。
源代码:
package com.breeze.concurrent.chapters1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* 线程的生命周期
* 一个线程从创建,到最终的消亡,需要经历多种不同的状态,这些不同的线程状态,由始至终也构成了线程生命周期的不同阶段。
* 线程的几个重要的状态如下:
* NEW:初始状态,线程被构建,但是还没有调用start方法。
* RUNNABLE:可运行状态,可运行状态包括:运行中状态和就绪状态
* BLOCKED:阻塞状态,处于这个状态的线程需要等待其他释放锁或者等待进入synchronized
* WAITING:表示等待状态,处于该状态的线程需要等待其他线程通知或中断操作,进而进入下一个撞他
* TIMED_WAITING:超时等待状态。可以在一定的时间自行返回
* TERMMINATED:终止状态,当前线程执行完毕
*
* Thread.start() 使线程进入从NEW状态转到Runnable状态
*
* Thread.sleep(long)、Thread.sleep(long, int)、
* Object.wait(long)、Object.wait(long,int)、
* Thread.join(long)、Thread.join(long, int)、
* LockSupport.parkNanos()、LockSupport.parkUntil() 使线程从Runnable状态转到TIMED_WAITING状态
*
*
*/
public class ThreadLifeCycle {
/**
* 创建四个线程timedWaitingThread、waitingThread、blockedThread01、blockedThread02
* timedWaitingThread线程,在while(true)循环中调用TimeUnit.SECONDS.sleep(long)方法来验证线程的TIMED_WARTING状态。
*
* waitingThread线程,获取当前类Class对象的synchronized锁,
* 在synchronized中使用线程的wait()方法,来验证线程的WAITING状态,调用wait()方法释放锁。
*
* blockedThread01线程,获取当前类Class对象的synchronized锁,
* 在while(true)循环中调用TimeUnit.SECONDS.sleep(long),使blockedThread01线程处于TIMED_WARTING状态,并一直持有锁。
* 此时如果调用notify的话,会唤醒waitingThread线程,由于锁被blockedThread01线程抢到并一直占有,waitingThread线程处于BLOCKED(阻塞)状态。
*
* blockedThread02线程,获取当前类Class对象的synchronized锁,
* blockedThread02线程尝试获取锁,由于blockedThread01线程抢到锁不释放锁,
* blockedThread02线程处于BLOCKED(阻塞)状态。
*/
public static void main(String[] args) {
//timedWaitingThread线程,在while(true)循环中调用TimeUnit.SECONDS.sleep(long)方法
//来验证线程的TIMED_WARTING状态。
Thread timedWaitingThread = new Thread(() ->{
while (true){
try {
TimeUnit.SECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"TIMED_WAITING_Thread");
// waitingThread线程,获取当前类Class对象的synchronized锁,
// 在synchronized中使用线程的wait()方法,来验证线程的WAITING状态,调用wait()方法释放锁。
Thread waitingThread = new Thread(() -> {
synchronized (ThreadLifeCycle.class){
while (true){
try {
//注意:wait()会释放锁
ThreadLifeCycle.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"WAITING_Thread");
// blockedThread01线程,获取当前类Class对象的synchronized锁,
// 在while(true)循环中调用TimeUnit.SECONDS.sleep(long),使blockedThread01线程处于TIMED_WARTING状态,并一直持有锁。
Thread blockedThread01 = new Thread(() -> {
while (true){
synchronized (ThreadLifeCycle.class){
try {
// 此时如果调用notify的话,会唤醒waitingThread线程,由于锁被blockedThread01线程抢到并一直占有,waitingThread线程处于BLOCKED(阻塞)状态。
//ThreadLifeCycle.class.notify();
TimeUnit.SECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Blocked_Thread-01");
// blockedThread02线程,获取当前类Class对象的synchronized锁,
// blockedThread02线程尝试获取锁,由于blockedThread01线程抢到锁不释放锁,
// blockedThread02线程处于BLOCKED(阻塞)状态。
Thread blockedThread02 = new Thread(() -> {
while (true){
synchronized (ThreadLifeCycle.class){
try {
TimeUnit.SECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Blocked_Thread-02");
timedWaitingThread.start();
//waitingThread线程会抢到锁然后释放锁,blockedThread01线程抢到锁不释放锁,blockedThread01线程会阻塞
waitingThread.start();
blockedThread01.start();
blockedThread02.start();
/**
* 验证方式:
* 1. 在命令行中输入jps,查看运行的进程
* 2. 输入jstack + 进程号,查看进程栈的信息
*注意:使用jps结合jstack命令可以分析线上生产环境的Java进程的异常信息
*
* 也可以直接点击IDEA下图所示的图表直接打印出线程的堆栈信息。
*/
}
}
扩展:线程常用方法释义:
1. sleep() 方法:
sleep(毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞状态,期间得不到cpu的时间片,等到时间过去了,线程重新进入可执行状态。(暂停线程,不会释放锁)
2.suspend() 和 resume() 方法:
挂起和唤醒线程,suspend e()使线程进入阻塞状态,只有对应的resume e()被调用的时候,线程才会进入可执行状态。(不建议用,容易发生死锁)
3. yield() 方法:
会使的线程放弃当前分得的cpu时间片,但此时线程任然处于可执行状态,随时可以再次分得cpu时间片。yield()方法只能使同优先级的线程有执行的机会。调用 yield()的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。(暂停当前正在执行的线程,并执行其他线程,且让出的时间不可知)
4.wait() 和 notify() 方法:
两个方法搭配使用,wait()使线程进入阻塞状态,调用notify()时,线程进入可执行状态。wait()内可加或不加参数,加参数时是以毫秒为单位,当到了指定时间或调用notify()方法时,进入可执行状态。(属于Object类,而不属于Thread类,wait()会先释放锁住的对象,然后再执行等待的动作。由于wait()所等待的对象必须先锁住,因此,它只能用在同步化程序段或者同步化方法内,否则,会抛出异常IllegalMonitorStateException.)
5.join()方法:
也叫线程加入。是当前线程A调用另一个线程B的join()方法,当前线程转A入阻塞状态,直到线程B运行结束,线程A才由阻塞状态转为可执行状态。
以上是Java线程唤醒和阻塞的五种常用方法,不同的方法有不同的特点,其中wait() 和 notify()是其中功能最强大、使用最灵活的方法,但这也导致了它们效率较低、较容易出错的特性,因此,在实际应用中应灵活运用各种方法,以达到期望的目的与效果!
- 上一篇: 腾讯一面:Java的线程池有哪几种状态?
- 下一篇: JVM 线程状态
猜你喜欢
- 2024-11-18 Java并发编程线程状态转换
- 2024-11-18 Java面试必考问题:线程的生命周期
- 2024-11-18 Java 19 虚拟线程的状态变化,停驻与锁定
- 2024-11-18 Java线程生命周期详解?
- 2024-11-18 线程从创建最终消亡,要经历的若干状态,你了解其中的多少?
- 2024-11-18 java线程状态之WAITING(等待)
- 2024-11-18 浅谈Java线程:线程基础知识扫盲
- 2024-11-18 Java线程在各个状态下调用start方法会发生什么事情?
- 2024-11-18 为什么Java中线程没有Running状态
- 2024-11-18 阻塞模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)