java多线程回顾2:生命周期与控制
1、 线程生命周期概述
线程的生命周期如下图:

2、 新建与就绪
当程序使用new关键字创建一个线程之后,线程就处于新建状态了。此时线程只是被分配了内存资源,初始化了成员变量。
当线程对象被调用了start()方法之后,该线程就处于就绪状态了。表示这个线程可以运行但还没有运行,至于线程何时开始运行,取决于jvm的线程调度器。
有一点值得注意,启动线程应该使用start()方法,而不是run()方法。如果使用run()方法,程序会把run()方法当成一个普通方法立刻执行,而不会启动新线程。
此外,也不可以对已就绪的线程再次调用start()方法,会引发异常。
3、 阻塞与运行
当就绪的线程获得CPU资源开始执行方法体,该线程就变成运行状态。当线程在运行的过程中被中断,则线程变为阻塞状态。被阻塞的线程在合适的时候会重新进入就绪状态,然后再次获取CPU资源,进入运行状态。
以下情况将使线程进入阻塞状态:
- 线程调用sleep方法,主动放弃所占CPU资源。
- 线程掉用了一个阻塞式IO方法,在方法返回前,线程被阻塞。
- 线程试图获取一个同步锁,但是该锁被其他线程占有。
- 线程在等待通知(线程同步notify)
- 线程调用suspend方法挂起。该方法容易死锁,少用。
以下情况将解除阻塞状态,使线程重新进入就绪状态:
- sleep方法计时结束
- 阻塞式IO方法已经返回
- 获取了同步锁
- 等到了其他线程发出的通知
- 调用resume方法解除了挂起状态
此外,调用yield方法可以使运行状态的线程直接转入就绪状态。
4、 线程死亡
以下三种情况时线程将死亡。
- run()方法执行结束,线程结束。
- 线程抛出了一个未捕获的Exception或Error
- 调用了线程的stop()方法。该方法容易死锁,少用。
注意,死亡状态的线程不能再次调用start()方法来启动,否则会引发异常。
5、线程控制
5.1join线程
举个例子,线程A在执行中调用线程B的join方法,线程A将被阻塞,直到线程B执行完为止。
线程代码如下:
//通过实现Runnable接口创建线程类
public class ThreadTwo implements Runnable{
private int i;
//run方法同样是线程的执行体
@Override
public void run() {
for (i = 0; i < 5; i++) {
//实现Runnable接口创建线程类时,只能使用Thread.currentThread()来获取当前线程
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
测试代码如下:
public class TestThreadJoin {
public static void main(String[] args) throws InterruptedException {
ThreadTwo st = new ThreadTwo();
new Thread(st,"打酱油的线程").start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==2) {
ThreadTwo st2 = new ThreadTwo();
Thread thread = new Thread(st2,"被join的线程");
thread.start();
//main线程调用了thread线程的join方法,必须等thread执行结束才会向下执行
thread.join();
}
}
}
}
测试结果如下:
main 0 打酱油的线程 0 main 1 打酱油的线程 1 main 2 打酱油的线程 2 打酱油的线程 3 被join的线程 0 打酱油的线程 4 被join的线程 1 被join的线程 2 被join的线程 3 被join的线程 4 main 3 main 4 main 5 main 6
在以上代码中,main线程的i等于2时,启动了“被join的线程”,这时main线程进入阻塞状态,只有“打酱油的线程”“ 被join的线程”在运行,等“被join的线程”运行完了,main线程才重新开始运行。
5.2后台线程
后台线程也称“守护线程”或“精灵线程”。jvm的垃圾回收线程就是典型的后台进程。
一般线程在被创建之后,其生命周期是独立的。而后台进程的生命周期与前台进程相关:当所有前台进程都死亡,后台进程也随之死亡。
使用thread.setDaemon(true)可将线程设为后台线程,且必须在线程启动前设置。
前台线程创建的线程默认为前台线程。
后台线程创建的线程默认为后台线程。
5.3线程睡眠sleep
Sleep方法是Thread类提供的一个静态方法,让当前线程进入阻塞状态,时间到了之后,线程会自动转入就绪状态。
5.4线程让步yield
yield方法和sleep方法类似,也是一个Thread类提供的静态方法,和sleep不同的是,yield是让线程转入就绪状态。
当某个线程调用了yield方法后,和当前线程优先级一样,或更高的线程会转入运行状态。
5.5线程优先级
Thread类提供了setPriority(int newPriority)方法和getPriority()方法来设置和获取线程优先级,优先级的范围通常在1-10之间,10是最高优先级。
不过不同系统的优先级数值可能不同,所以通常推荐使用Thread类的三个静态常量来设置优先级,分别是MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY。
java多线程回顾2:生命周期与控制的更多相关文章
- Java多线程——线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- Java多线程-线程的生命周期
线程可以分为4个状态:New(新生),Runnable(可运行):为了方便分析,还可将其分为:Runnable与Running.blocked(被阻塞),Dead(死亡). 与人有生老病死一样,线程也 ...
- WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]
原文:WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇] 在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来 ...
- Java 并发 线程的生命周期
Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a) New 新建 b) Runnable 可运行 c) Running 运行 (调用 ...
- Java精选笔记_多线程(创建、生命周期及状态转换、调度、同步、通信)
线程概述 在应用程序中,不同的程序块是可以同时运行的,这种多个程序块同时运行的现象被称作并发执行. 多线程可以使程序在同一时间内完成很多操作. 多线程就是指一个应用程序中有多条并发执行的线索,每条线索 ...
- Java基础知识笔记(四:多线程基础及生命周期)
一.多线程基础 编写线程程序主要是构造线程类.构造线程类的方式主要有两种,一种是通过构造类java.lang.Thread的子类,另一种是通过构造方法实现接口java.lang.Runnable的类. ...
- java并发编程基础—生命周期与线程控制
一.线程生命周期 线程被创建启动以后,他既不是一启动就进入执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(Running).阻塞(Bloc ...
- 「小程序JAVA实战」小程序视频播放的时候生命周期的控制(56)
转自:https://idig8.com/2018/09/23/xiaochengxujavashizhanxiaochengxushipinbofangdeshihoushengmingzhouqi ...
- Java - JVM - 类的生命周期
概述 简述 JVM 里 类的生命周期 上次写了 30%, 居然丢了 难受, 又要重新写 类的生命周期 加载 使用 卸载 1. 加载 概述 类型的加载 大体流程 装载 连接 验证 准备 解析(可选的) ...
随机推荐
- [NOIp2018] luogu P5020 货币系统
还在补暑假作业. 题目描述 你有一个由 NNN 种面值的货币组成的货币系统.定义两个货币系统等价,当且仅当 ∀x∈N∗\forall x\in\N^*∀x∈N∗ 要么同时能被两个货币系统表示,要么同时 ...
- [牛客网NOIP赛前集训营-提高组(第一场)]C.保护
链接:https://www.nowcoder.com/acm/contest/172/C来源:牛客网 题目描述 C国有n个城市,城市间通过一个树形结构形成一个连通图.城市编号为1到n,其中1号城市为 ...
- SVN工具常用功能总结
使用SVN作为版本管理工具,可以使用VisualSVN Server+TortoiseSVN搭建SVN版本控制系统,组长安装VisualSVN Server,组员安装TortoiseSVN. Tort ...
- java命令行导出、导入sql文件
@IocBean public class SqlCommandModel{ //用户名 @Inject("java:$conf.get('jdbc.username')") pr ...
- opencv::源码编译
环境:win10.vs2017.cmake .java.python3.7默认安装. opencv源码:opencv-.zip opencv拓展库源码:opencv_contrib-.zip (注意: ...
- Vue全局组件注册
通过Vue.component(‘组件名’, {配置对象})注册全局组件 在main.js中注册全局组件 test import Vue from 'vue' import App from './A ...
- 开源造轮子:一个简洁,高效,轻量级,酷炫的不要不要的canvas粒子运动插件库
一:开篇 哈哈哈,感谢标题党的莅临~ 虽然标题有点夸张的感觉,但实际上,插件库确实是简洁,高效,轻量级,酷炫酷炫的咯.废话不多说,先来看个标配例子吧: (codepen在线演示编辑:http://co ...
- java架构之路-(Redis专题)redis面试助力满分+
1.Redis支持的数据类型? 答:五种,在第一节redis相关的博客我就说过,String,Hash,List,Set,zSet,也就是我们的字符串,哈希,列表,集合,有序集合五种.结构图如下. 2 ...
- python的递归函数怎么用
在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数 理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰 使用递归函数需要注意防止栈溢出.由于栈的大小不 ...
- 小白学 Python(12):基础数据结构(字典)(上)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...