一、线程的生命周期

  (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:

  1. public class MyThread extends Thread {
  2. public void run() {
  3. for (int i = 0; i < 100; i++) {
  4. if ((i) % 10 == 0) {
  5. System.out.println("‐‐‐‐‐‐‐" + i);
  6. }
  7. System.out.print(i);
  8. try {
  9. Thread.sleep(1000);
  10. System.out.print(" 线程睡眠1秒!\n");
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. }
  16. public static void main(String[] args) {
  17. new MyThread().start();
  18. }
  19. }

  注意

    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:

  1. public class WaitingTest {
  2. public static Object obj = new Object();
  3. public static void main(String[] args) {
  4. // 演示waiting
  5. new Thread(new Runnable() {
  6. @Override
  7. public void run() {
  8. while (true){
  9. synchronized (obj){
  10. try {
  11. System.out.println( Thread.currentThread().getName() +"=== 获取到锁对象,调用wait方法,进入waiting状态,释放锁对象");
  12. obj.wait(); //无限等待
  13. //obj.wait(5000); //计时等待, 5秒 时间到,自动醒来
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. }
  17. System.out.println( Thread.currentThread().getName() + "=== 从waiting状
  18. 态醒来,获取到锁对象,继续执行了");
  19. }
  20. }
  21. }
  22. },"等待线程").start();
  23.  
  24. new Thread(new Runnable() {
  25. @Override
  26. public void run() {
  27. // while (true){ //每隔3秒 唤醒一次
  28. try {
  29. System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 等待3秒钟");
  30. Thread.sleep(3000);
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. synchronized (obj){
  35. System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 获取到锁对
  36. 象,调用notify方法,释放锁对象");
  37. obj.notify();
  38. }
  39. }
  40. // }
  41. },"唤醒线程").start();
  42. }
  43. }

  一个调用了某个对象的 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 之 线程的生命周期(线程状态)的更多相关文章

  1. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  2. Java多线程——线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  3. Java线程的生命周期与状态流转

    上图是一个线程的生命周期状态流转图,很清楚的描绘了一个线程从创建到终止的过程. 这些状态的枚举值都定义在java.lang.Thread.State下 NEW:毫无疑问表示的是刚创建的线程,还没有开始 ...

  4. JAVA基础知识之多线程——线程的生命周期(状态)

    线程有五个状态,分别是新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死亡(Dead). 新建和就绪 程序使用new会新建一个线程,new出的对象跟普通对象一 ...

  5. Java线程生命周期与状态切换

    前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...

  6. Java 并发 线程的生命周期

    Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a)     New 新建 b)     Runnable 可运行 c)     Running 运行 (调用 ...

  7. Java并发编程:线程的生命周期是个怎样的过程?

    前言 在日常开发过程中,如果我们需要执行一些比较耗时的程序的话,一般来说都是开启一个新线程,把耗时的代码放在线程里,然后开启线程执行.但线程是会耗费系统资源的,如果有多个线程同时运行,互相之间抢占系统 ...

  8. Java精选笔记_多线程(创建、生命周期及状态转换、调度、同步、通信)

    线程概述 在应用程序中,不同的程序块是可以同时运行的,这种多个程序块同时运行的现象被称作并发执行. 多线程可以使程序在同一时间内完成很多操作. 多线程就是指一个应用程序中有多条并发执行的线索,每条线索 ...

  9. Java-多线程第三篇3种创建的线程方式、线程的生命周期、线程控制、线程同步、线程通信

    1.Java使用Thread类代表线程.     所有的线程对象必须是Thread类或其子类的实例. 当线程继承Thread类时,直接使用this即可获取当前线程,Thread对象的getName() ...

随机推荐

  1. 火车头data下任务文件夹的SpiderResult.db3文件用什么软件打开

    火车头采集器默认是用sqlite数据库来保存数据的,新建一个采集,打开data/任务/发现有一个SpiderResult.db3文件,.db3是sqlite的存储文件后缀,那么要如何查看这些文件呢?用 ...

  2. RabbitMQ六种队列模式-简单队列模式

    前言 RabbitMQ六种队列模式-简单队列 [本文]RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...

  3. 微信小程序之简单记账本开发记录(七)

    记账本已经可以实现添加和删除的功能 现在只需要将上述步骤重复一遍便可将另一个界面做出来. 大体上已制作完成,如果在细节上有变动会在这一篇更新 总体来说,这个作业让我对微信小程序的开发有了更多地认识,大 ...

  4. 将行数据转换成Java(POJO)对象

    工作中经常会遇到将行数据转换成Java(POJO)对象的场景,其中关于字段校验和类型转换的处理繁琐而冗余,对于有代码洁癖的人着实不能忍.这里分享下自己封装的工具代码,也许能够帮助你更简单地完成此类任务 ...

  5. ##C++ format 格式化字符串

    C++ format 格式化字符串实现方式 1. http://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprint ...

  6. Java 集合系列之五:Map基本操作

    1. Java Map 1. Java Map 重要观点 Java Map接口是Java Collections Framework的成员.但是它不是Collection 将键映射到值的对象.一个映射 ...

  7. ASP.NET Core WebApi基于Redis实现Token接口安全认证

    一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebSer ...

  8. kudu 介绍

    kudu的好处: 快速的olap 列式存储,Hadoop parquet 的一种替代方案 对数据的顺序处理和随机处理都很高效 * High availability. Tablet Servers a ...

  9. c# 枚举类型怎么用?

    有很多将枚举类型的都没有说详细...所以我这里贴出来一下,免得我忘记.................................. using System; using System.Coll ...

  10. [原创]K8域控植入脚本生成器(内网渗透/RPC不可用解决方案)

    0x001 简介 当IPC或WMI无法访问域内机器时,可通过脚本上控. 我们可以在个人机的开机注销重启脚本里配置持久化. 域环境下同样也有开机脚本,但得在在域控机器配置 可以使用BAT\VBS等脚本, ...