专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java并发编程(一)-Java线程状态及其转换(理论+实战)

temp10 2024-10-25 17:05:10 java教程 13 ℃ 0 评论

最近在悟空问答上面经常见到有人咨询关于Java并发编程的问题,因此准备写一些文章进行这方面的介绍,以帮助有疑惑的人,或者是即使没有疑惑但确实是没有时间整理的人。本文是第一部分,主要介绍Java线程六种状态及其转换,并附加编码实例。好多文章介绍Java线程是5种状态,分别为为初始状态(new)就绪状态(Runnable)运行状态(Running)阻塞状态(Blocked)终止状态(Dead)

实际上本人更倾向于六种状态,理由主要是基于Thread的源码并通过编程进行了验证。在Thread源码的状态枚举类型中,实际上定义了六种状态,分别是初始状态(NEW)、运行状态(RUNNABLE)、阻塞状态(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)、终止(TERMINATED)六种状态。下面分别将分别介绍这六种状态:

Java并发编程(一)-Java线程状态及其转换(理论+实战)

  1. 初始状态(NEW):实例化线程对象未调用start方法之前,线程处于初始状态。
  2. 运行状态(RUNNABLE):实际运行状态包括就绪(ready,即被主线程或其他线程调用start方法启动)和运行中(running,获取CPU执行时间,线程得以执行)两种状态。
  3. 阻塞(BLOCKED):获取锁或其他资源之前线程被阻塞,处于阻塞状态。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程通知或被中断。
  5. 超时等待(TIMED_WAITING):该状态与WAITING状态不同的是,它可以在指定的时间后自行返回。
  6. 终止(TERMINATED):表示该线程执行结束。

如果想查看线程状态源码,可参见Thread类:

下面看一下这六种状态是如何转换的:

我们知道Java线程主要通过两种方式来实现,一种是实现Runnable接口,一种是继承Thread类。线程被创建并被启动后,就开始了它的生命周期。Java线程的生命周期有长又有短,并且在其生命周期内进行各种状态的转化。线程在被实例化时进入NEW状态,调用start方法后会进入Runnable状态。Runnable可以说一种核心状态,Runnable与Waiting、Timed_Waiting、Blocked等状态进行转化,直至执行完成进入TERMINATED状态。

Runnable和Waiting状态之间的转化,主要在线程内调用Object.wait()、Thread.join()、LockSupport.park()方法时进入Waiting状态。当其他线程调用Object.notify()随机通知单线程,Objec.notifyAll()通知所有线程,LockSupport.unpark(Thread)方法时被唤醒,若其他线程不释放资源,线程将一直处于Waiting状态。

Runnable和Timed_Waiting状态之间的转化,主要是线程内调用Thread.sleep(long)、Objec.wait(long)等方法时进入Timed_Waiting状态。当其他与其竞争资源的线程调用Object.notify()、Objec.notifyAll()等方法时线程会被唤醒。当超过超时时间时线程也会自动唤醒,这也是Timed_Waiting状态与Waiting状态的最大区别。

当线程尝试获取锁而未获取到时,线程从Runnable状态进入Blocked状态。而当线程获取到锁后从Blocked状态进入Runnable状态。

下面将结合代码示例和jconsole来查看进程的不同状态。本文主要是通过生产者和消费者示例程序来验证Java 线程的各种状态。在示例中启动了一个消费者和两个生产者,先启动消费者后等待,再启动生产者休眠一段时间后,开始进行生产。当生产到一定数量后,通知消费者开始消费,最后一边生产一边消费。

主程序:

生产者run方法:

消费者run方法:

执行主程序,查看程序的状态。

初始启动后,各程序处于NEW状态:

查看consumer状态,因为程序执行了object.wait(),程序处于WAITING状态:

consumer消费一个产品后,会调用Thread.sleep()类,程序就进入TIMED_WAITING状态:

生产者和消费者在生产或消费时都会操作list,竞争锁synchronized(list),此时会进入BLOCKED状态:

程序在执行过程中处于RUNNABLE状态:

当然还有一种状态是TERMINATED,这个比较好理解,程序执行完成处于终止状态,不再详细描述。

附录:

主要是讲述一下如何进入console查看线程状态。

配置好Java环境变量后,执行jconsole命令:

进入jconsole界面,选择你执行的程序:

点击进入,查看你的线程:

喜欢动手的阅读者,可能会发现一个bug,不知道你发现了没有?

本人具有多年的java开发经验,熟悉多种框架,熟悉网络编程,熟悉java安全编程,熟悉大数据,熟悉多种安全协议,熟悉并发编程,有兴趣的同学可以互相关注,互相学习!!!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表