一、线程的生命周期
(1)新建状态
new 好了一个线程对象,此时和普通的 Java对象并没有区别。
(2)就绪
就绪状态的线程是具备被CPU调用的能力和状态,也只有这个状态的线程才能被CPU调用。即线程调用了 start() 方法
(3)运行
运行状态就是当前线程正在被CPU调度执行。
(4)阻塞
从运行状态到阻塞状态有几种情况:
① sleep()
② wait()
③ join()
④ suspend() 已过时
从阻塞回到就绪状态:
① sleep() 时间到,sleep() 被打断 interrupt()
② notify()
③ 加塞的线程结束
④ 占用锁的线程释放锁
⑤ resume() 已过时
(5)死亡
从运行到死亡:① run()正常结束 ② run()遇到异常但是没处理 ③ 其他线程把你stop()(已过时)
图解:
二、线程状态概述
当线程被创建并启动以后,并没有直接进入执行状态,还有其他的状态。
在线程的生命周期中, java.lang.Thread.State 这个枚举中给出了六种线程状态:
线程之间的状态转换:
三、Timed Waiting (计时等待)
Timed Waiting在API中的描述为:一个正在限时等待另一个线程执行一个(唤醒)动作的线程处于这一状态。
当调用了 sleep 方法之后,当前执行的线程就进入 “休眠状态”,其实就是Timed Waiting(计时等待)。
Demo:
public class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
if ((i) % 10 == 0) {
System.out.println("‐‐‐‐‐‐‐" + i);
}
System.out.print(i);
try {
Thread.sleep(1000);
System.out.print(" 线程睡眠1秒!\n");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new MyThread().start();
}
}
注意:
1. 进入 TIMED_WAITING 状态的一种常见情形是调用的 sleep 方法,单独的线程也可以调用,不一定非要有协作关系
2. 为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠
3. sleep与锁无关,线程睡眠到期自动苏醒,并返回到Runnable(可运行)状态。
Tips: sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始立刻执行。
线程状态图:
四、Blocked (锁阻塞)
Blocked状态在API中的介绍为:一个正在阻塞等待一个监视器锁(锁对象)的线程处于这一状态。
如当线程 A 与线程B 在代码中使用同一个锁,如果线程 A 获取到锁,线程A 进入 Runnable 状态,那么线程B就进入到 Blocked 锁阻塞状态。
Blocked 线程状态图:
五、Waiting (无限等待)
Waiting 状态介绍为:一个正在无限期等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态。
Demo:
public class WaitingTest {
public static Object obj = new Object();
public static void main(String[] args) {
// 演示waiting
new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (obj){
try {
System.out.println( Thread.currentThread().getName() +"=== 获取到锁对象,调用wait方法,进入waiting状态,释放锁对象");
obj.wait(); //无限等待
//obj.wait(5000); //计时等待, 5秒 时间到,自动醒来
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( Thread.currentThread().getName() + "=== 从waiting状
态醒来,获取到锁对象,继续执行了");
}
}
}
},"等待线程").start(); new Thread(new Runnable() {
@Override
public void run() {
// while (true){ //每隔3秒 唤醒一次
try {
System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 等待3秒钟");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 获取到锁对
象,调用notify方法,释放锁对象");
obj.notify();
}
}
// }
},"唤醒线程").start();
}
}
一个调用了某个对象的 Object.wait 方法的线程会等待另一个线程调用此对象的 Object.notify() 方法或 Object.notifyAll() 方法。
注意:waiting状态并不是一个线程的操作,它体现的是多个线程间的通信,可以理解为多个线程之间的协作关系,多个线程会争取锁,同时相互之间又存在协作关系。
扩展:
当多个线程协作时,比如A,B线程,如果A线程在Runnable(可运行)状态中调用了wait()方法那么A线程就进入了Waiting(无限等待)状态,同时失去了同步锁。
假如这个时候B线程获取到了同步锁,在运行状态中调用了notify()方法,那么就会将无限等待的A线程唤醒。注意是唤醒,如果获取到锁对象,那么A线程唤醒后就进入Runnable(可运行)状态;如果没有获取锁对象,那么就进入到Blocked(锁阻塞状态)。
Waiting 线程状态图:
六、线程状态转换
Tips:
发现Timed Waiting(计时等待) 与 Waiting(无限等待) 状态联系还是很紧密的,比如Waiting(无限等待) 状态中wait方法是空参的,而timed waiting(计时等待) 中wait方法是带参的。
这种带参的方法,其实是一种倒计时操作,相当于我们生活中的小闹钟,我们设定好时间,到时通知,可是如果提前得到(唤醒)通知,那么设定好时间在通知也就显得多此一举了,那么这种设计方案其实是一举两得。如果没有得到(唤醒)通知,那么线程就处于Timed Waiting状态,直到倒计时完毕自动醒来;如果在倒计时期间得到(唤醒)通知,那么线程从Timed Waiting状态立刻唤醒。
Java 之 线程的生命周期(线程状态)的更多相关文章
-
Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
-
Java多线程——线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
-
Java线程的生命周期与状态流转
上图是一个线程的生命周期状态流转图,很清楚的描绘了一个线程从创建到终止的过程. 这些状态的枚举值都定义在java.lang.Thread.State下 NEW:毫无疑问表示的是刚创建的线程,还没有开始 ...
-
JAVA基础知识之多线程——线程的生命周期(状态)
线程有五个状态,分别是新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死亡(Dead). 新建和就绪 程序使用new会新建一个线程,new出的对象跟普通对象一 ...
-
Java线程生命周期与状态切换
前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...
-
Java 并发 线程的生命周期
Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a) New 新建 b) Runnable 可运行 c) Running 运行 (调用 ...
-
Java并发编程:线程的生命周期是个怎样的过程?
前言 在日常开发过程中,如果我们需要执行一些比较耗时的程序的话,一般来说都是开启一个新线程,把耗时的代码放在线程里,然后开启线程执行.但线程是会耗费系统资源的,如果有多个线程同时运行,互相之间抢占系统 ...
-
Java精选笔记_多线程(创建、生命周期及状态转换、调度、同步、通信)
线程概述 在应用程序中,不同的程序块是可以同时运行的,这种多个程序块同时运行的现象被称作并发执行. 多线程可以使程序在同一时间内完成很多操作. 多线程就是指一个应用程序中有多条并发执行的线索,每条线索 ...
-
Java-多线程第三篇3种创建的线程方式、线程的生命周期、线程控制、线程同步、线程通信
1.Java使用Thread类代表线程. 所有的线程对象必须是Thread类或其子类的实例. 当线程继承Thread类时,直接使用this即可获取当前线程,Thread对象的getName() ...
随机推荐
-
springframwork历史版本下载地址
http://sourceforge.net/projects/springframework/files/springframework-2/
-
Java语言程序设计-助教篇
1. 给第一次上课(软件工程)的老师与助教 现代软件工程讲义 0 课程概述 给学生:看里面的第0个作业要求 2. 助教心得 美国视界(1):第一流的本科课堂该是什么样?(看里面的助教部分) 助教工作看 ...
-
linux rzsz(lrzsz)安装
lrzsz 官网入口:https://ohse.de/uwe/software/lrzsz.html lrzsz是一个unix通信套件提供的X,Y,和ZModem文件传输协议,可以用在windows与 ...
-
《学习之道》第八章孤军奋战or组队合作
孤军奋战与组队合作:别再苦思冥想,拖延行为需要差别对待 对拖延我得提一个小建议,你要暂时把自己与那些会干扰你的人和事隔离开.自己到一个房间里去,或者去图书馆,这样就没什么事能让你分心了. 如果一门课让 ...
-
Jedis 简单案例
POM 依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> < ...
-
poj3417lca+树上差分
/* 给定n个点的树,在其中加入m条新边(称为非树边) 现在可以割断一条树边,一条非树边,使图分裂成两个联通块,请问有几种切割方式 对树边进行分情况讨论 如果树边不处在环中,则割断这条树边后可以割断任 ...
-
Elasticsearch冷热集群搭建
ES版本:6.2.4 集群环境:7台机器,每台部署一个master节点.其中3台部署2个hot节点,另外4台部署2个warm节点.共21个节点. 1. 挂盘 按实际情况分盘,一个机子上的2个data节 ...
-
剑指offer-特定二维数组中查找一个元素是否存在-二分搜索-二维数组
int [][] array ={ {1,2,8,9}, {2,4,9,12}, {4,7,10,13}, {6,8,11,19} }; 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都 ...
-
[转]Grunt 新手一日入门
本文转自:http://yujiangshui.com/grunt-basic-tutorial/ 当时学习 Grunt 的时候,真是很头疼.分了两个时间段,学习了两次才硬啃下来,之后才能用在项目中. ...
-
转:系统吞吐量(TPS)、用户并发量、性能测试概念和公式
PS:下面是性能测试的主要概念和计算公式,记录下: 一.系统吞度量要素: 一个系统的吞度量(承压能力)与request对CPU的消耗.外部接口.IO等等紧密关联. 单个reqeust 对CPU消耗越高 ...