Java并发之线程状态及Thread常用方法
本篇文章主要讲解线程的虚拟机状态和线程基本方法,希望可以加深对线程的使用理解。
一、线程的虚拟机状态
线程对象在不同的运行期间有不同的状态,状态信息定义在Thread公共静态枚举java.lang.Thread.State中,线程可以处于以下6种状态,一个线程在给定的时间点只能处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
NEW
新创建的线程在尚未启动时处于此状态。即new Thread()一个线程在未调用start()方法时处于此状态。
RUNNABLE
在Java虚拟机中执行的线程处于这种状态。线程调用start()方法后,线程进入可运行线程池(就绪状态),接受CPU调度执行。该状态是线程处于正常运行中,
这个状态下发生的等待一般是其他系统资源, 而不是锁, Sleep等。
BLOCKED
阻塞等待监视器锁定的线程处于此状态。这个状态一般发生在多线程有同步操作的情况下,比如一个线程正在等待一个线程synchronized 块的执行释放,
或者可重入的 synchronized块里别人调用wait()方法, 也就是这里是线程在等待进入临界区。
WAITING
无限期地等待另一个线程执行特定动作的线程处于这种状态。
1)这个状态是当线程获得了对象锁之后,调用了wait()方法,等待该对象锁的拥有者调用notify()或notifyAll()唤醒。
2)当在主线程里,调用子线程的join()后,主线程也会处于waiting状态,等待join的子线程执行完成后,继续执行。
TIMED_WAITING
正在等待另一个线程执行动作达到指定的等待时间的线程处于此状态。一般出现在一个线程在其它线程调用sleep(long)或wait(long),join(long)后等待的情况。
TERMINATED
退出的线程处于这种状态。比如run方法正常执行完退出,线程调用stop()方法强制停止退出,线程运行时出现异常中断退出等。
BLOCKED 和 WATING 的区别
BLOCKED是线程在同步锁阻塞后进入Lock Pool等待重新获取锁执行, WATING是线程在获得同步锁后进入Waiting Pool等待别人notify唤醒继续执行。一个在临界点外部等待进入,一个在临界点里面等待唤醒。
调用与线程相关的方法是造成线程状态改变的主要原因,在调用与线程有关的方法后,线程进入不同的状态,这些状态之间有些是可以相互切换的,但有些的只能是单向切换的。

二、线程Thread常用方法
对使用Java并发编程的,一定会涉及到多线程,说到线程就离不开Thread这个类,我们先不管Thread实现原理是啥,从实际使用的角度出发,我们总结一下线程的常用方法都有哪些,以及怎么使用,会遇到哪些问题。
1.start()方法
start方法是为了启动线程运行。当线程创建后,调用了start(),此时线程处于就绪状态,等待CPU调度准备执行。
2.run()方法
run()方法里是线程具体的代码执行逻辑,不管是继承Thread类还是实现Runnable,都会覆写run方法。当调用了线程的start(),CPU有空闲时便会执行run方法。
是否可以直接调用run()方法?可以。但是,直接调用就相当于对一个普通对象的普通方法调用,也就没有了线程异步调度,一般不会直接调用。
3.sleep方法
sleep()是让当前正在执行的线程在指定的毫秒数内休眠(暂停执行),这个当前线程即Thread.currentThread()返回的线程。
线程的sleep()不会释放当前线程持有的锁,而是让出CPU资源给其他线程。
4.currentThread()方法
Thread.currentThread()返回的是执行的代码片段正在被那个线程调用的信息。如Thread.currentThread().getId()得到是被调用线程的唯一标识ID;Thread.currentThread().getName()得到是被调用线程的线程名称。
注意currentThread()与this的使用区别。
5.wait()
该方法是Object类的方法,用来将线程置入“等待执行队列”中。
在调用wait()方法前,只能在同步方法或同步代码块中调用wait()方法,即线程必须获得对象级别锁,否则会抛出IllegalMonitorStateException异常(RunntimeException的子类)。
wait()方法作用是使当前执行代码的线程进行等待,执行wait()后,在wait()所在的代码行处线程将停止继续执行,当前线程的对象锁释放,直到被通知唤醒或中断为止。 在继续执行wait()后面代码之前,该线程需要重新获得对象锁才可以继续执行。
6.notify()方法
该方法是Object类的方法。
notify()方法也需要在同步方法或同步块中调用,即在调用前,线程必须获得对象级别锁,否则也会抛出IllegalMonitorStateException异常。
该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程在等待,则由线程规划器挑选其中一个呈wait()状态的线程,对其通知唤醒,使它重新获取该对象的对象锁,继续执行后续代码。
执行notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象锁,而是要等到该执行notify()的线程把程序执行完。也就是退出synchronized()代码块后,当前线程才会释放锁,此时去通知呈wait状态的线程去重新获取该对象锁。
notify()是用来唤醒持有该对象锁的等待池中的某一个线程;notifyAll()是用来唤醒持有该对象锁的等待池中的所有线程。
7.yield()方法
yield()方法是让出当前的CPU资源,将它给其它的任务去占用CPU执行。
暂停当前正在执行的的线程,去执行其他线程。让当前正在执行的线程处于可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
8.join()方法
join()方法的作用是当使所属的子线程对象正在执行run()方法中的任务时,而使当前线程进行无限期的阻塞,直到子线程销毁后再继续执行当前线程后续的代码。其作用就是等待线程对象销毁。
很多情况下,主线程创建,并启动了子线程,如果子线程中要进行大量的长时间的运行,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完后再结束,就要在主线程中调用子线程对象的join()方法了。
9.interrupt()方法
用来中断线程运行,但并不是像在循环里break那样,马上停止循环。
线程调用interrupt()方法仅仅是在调用的线程里设置了停止的标记,并不是立即停止线程。标记为是记在this(线程对象)里。
10.interrupted()方法、isInterrupted()方法
interrupted()返回当前线程是否已经中断的标记值,并清除中断标记位。注意是当前线程currentThread()的标记,源码片段如下,
public static boolean interrupted() { return currentThread().isInterrupted(true); }
isInterrupted()返回是调用该方法的对象的线程的中断标记值。源码片段如下,
public boolean isInterrupted() { return isInterrupted(false); }
两者区别:
interrupted()是静态方法(它测试的是当前线程的中断状态),并且有清除标记功能,isInterrupted()是实例方法(它测试的是实例对象所表示的线程的中断状态)。
开发人员一般会根据中断标记的值来决定是否中断线程的运行,常用的是判断中断标记值手动抛出异常的方式来达到停止线程运行的目的。
Java并发之线程状态及Thread常用方法的更多相关文章
- Java中的线程状态转换和线程控制常用方法
Java 中的线程状态转换: [注]:不是 start 之后就立刻开始执行, 只是就绪了(CPU 可能正在运行其他的线程). [注]:只有被 CPU 调度之后,线程才开始执行, 当 CPU 分配给你的 ...
- [译]线程生命周期-理解Java中的线程状态
线程生命周期-理解Java中的线程状态 在多线程编程环境下,理解线程生命周期和线程状态非常重要. 在上一篇教程中,我们已经学习了如何创建java线程:实现Runnable接口或者成为Thread的子类 ...
- Java基础教程——线程状态
线程状态 JAVA定义了6种线程状态: Thread.State public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, ...
- Java线程状态及Thread类中的主要方法
要想实现多线程,就必须在主线程中创建新的线程对象. 不论什么线程一般具有5种状态,即创建,就绪,执行,堵塞,终止. 创建状态: 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时 ...
- Java基础之线程——派生自Thread类的子类(TryThread)
控制台程序. 程序总是至少有一个线程,程序开始执行时就会创建这个线程.在普通的Java应用程序中,这个线程从mian()方法的开头启动. 要开始执行线程,可以调用Thread对象的start()方法. ...
- Java并发之线程
在前面我们介绍的一些内容中,我们的程序都是一条执行流,一步一步的执行.但其实这种程序对我们计算机的资源的使用上是低效的.例如:我们有一个用于计算的程序,主程序计算数据,在计算的过程中每得到一个结果就需 ...
- Java并发之线程间的协作
上篇文章我们介绍了synchronized关键字,使用它可以有效的解决我们多线程所带来的一些常见问题.例如:竞态条件,内存可见性等.并且,我们也说明了该关键字主要是一个加锁和释放锁的集成,所有为能获得 ...
- Java并发之线程中断
前面的几篇文章主要介绍了线程的一些最基本的概念,包括线程的间的冲突及其解决办法,以及线程间的协作机制.本篇主要来学习下Java中对线程中断机制的实现.在我们的程序中经常会有一些不达到目的不会退出的线程 ...
- Java并发之线程管理(线程基础知识)
因为书中涵盖的知识点比较全,所以就以书中的目录来学习和记录.当然,学习书中知识的时候自己的思考和实践是最重要的.说到线程,脑子里大概知道是个什么东西,但很多东西都还是懵懵懂懂,这是最可怕的.所以想着细 ...
随机推荐
- Ubuntu 18.04 的网络配置
netplan简介 目前,ubuntu18.04上使用了netplan 作为网络配置工具:在终端上配置网络参数跟之前的版本有比较大的差别 Netplan工作流程如下图所示:通过读取 /etc/net ...
- MFC string char cstring 类型转换
在Unicode环境下用以下转换: CString z_strCurtTime = _T(""); // 获取当前时间 CTime z_tCurTime = CTime::GetC ...
- MSSQL 备份与恢复
建立维护计划,需启用<SQL Server 代理>服务 建立三个子作业: 1. 按周进行的全备份,每周日零点执行 2. 按天进行的差异备份,每天中午12点执行 3. 按小时执行的事务日志备 ...
- 远程桌面连接无法验证您希望连接的计算机的身份-mac连接远程桌面
在使用Mac(苹果笔记本)连接远程桌面的时候提示:”远程桌面连接无法验证您希望连接的计算机的身份”,具体异常如截图:解决方法如下:1. 登录云服务器.2. 打开运行,然后输入命令gpedit.msc, ...
- ZT自贴吧 说说你是怎么和恋人确定恋爱关系的?
http://www.baidu.com/link?url=svJFMqibXXhJUiGDaDr1obOyrIb9o0TqO5JWFtMuM-l7ndaRlGMyuRQKCOHh-Pj0
- UID卡修改&UID锁死修复
好久没发RFID类文章,最近有小伙伴问到UID卡的问题,在这里就写一写吧. 首先是UID修改的问题,只要卡是UID卡,就都可以修改UID,首先读卡器连接电脑,卡片放到读卡器上. 然后我们要用一个工具, ...
- Dispatch groups 与任务同步
https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingG ...
- ADF中VO的查询方法比较
getRowCount(),getQueryHitCount(oracle.jbo.server.ViewRowSetImpl),getEstimatedRangePageCount,getCappe ...
- Adobe flash player 因过期而遭到阻止解决办法
最近使用谷歌浏览器时总是提示Adobe flash player 因过期而遭到阻止,这让人很头痛,基本上就是打开一个网页就会弹出一个提示,下面是解决办法. 问题的截图界面: 解决方法:在chrome浏 ...
- Pollard_rho 因数分解
Int64以内Rabin-Miller强伪素数测试和Pollard 因数分解的算法实现 选取随机数\(a\) 随机数\(b\),检查\(gcd(a - b, n)\)是否大于1,若大于1则\(a - ...