精华内容
下载资源
问答
  • java多线程之线程的生命周期

    千次阅读 2017-06-23 10:04:11
    线程也是有生命周期的,也是存在不同的状态的,状态相互之间的转换. 线程对象的状态存放在Thread类的内部类(State)中: 注意:Thread.State类其实是一个枚举类.因为线程对象的状态是固定的,只有6种,此时使用枚举

    1.生命周期

    一个事物从出生的那一刻开始到最终死亡中间的整个过程.在事物的漫长的生命周期过程中,总会经历不同的状态(婴儿状态/青少年状态/中年状态/老年状态...).线程也是有生命周期的,也是存在不同的状态的,状态相互之间的转换.

    线程对象的状态存放在Thread类的内部类(State)中:
    注意:Thread.State类其实是一个枚举类.因为线程对象的状态是固定的,只有6种,此时使用枚举来表示是



    2.线程生命周期

    1:新建状态(new)

    使用new创建一个线程对象,仅仅在堆中分配内存空间,在调用start方法之前. 新建状态下,线程压根就没有启动,仅仅只是存在一个线程对象而已.Thread t = new Thread();//此时t就属于新建状态当新建状态下的线程对象调用了start方法,此时从新建状态进入可运行状态.线程对象的start方法只能调用一次,否则报错:IllegalThreadStateException.
    2:可运行状态(runnable)

    分成两种状态,ready和running。分别表示就绪状态和运行状态。
    就绪状态:线程对象调用start方法之后,等待JVM的调度(此时该线程并没有运行).
    运行状态:线程对象获得JVM调度,如果存在多个CPU,那么允许多个线程并行运行.


    3:阻塞状态(blocked)

    正在运行的线程因为某些原因放弃CPU,暂时停止运行,就会进入阻塞状态.此时JVM不会给线程分配CPU,直到线程重新进入就绪状态,才有机会转到运行状态.阻塞状态只能先进入就绪状态,不能直接进入运行状态.
    阻塞状态的两种情况:
                1):当A线程处于运行过程时,试图获取同步锁时,却被B线程获取.此时JVM把当前A线程存到对象的锁池中,A线程进入阻塞状态.
                2):当线程处于运行过程时,发出了IO请求时,此时进入阻塞状态.
    4:等待状态(waiting)(等待状态只能被其他线程唤醒):

    此时使用的无参数的wait方法,
           1):当线程处于运行过程时,调用了wait()方法,此时JVM把当前线程存在对象等待池中.
    5:计时等待状态(timed waiting)(使用了带参数的wait方法或者sleep方法) 
           1):当线程处于运行过程时,调用了wait(long time)方法,此时JVM把当前线程存在对象等待池中.
           2):当前线程执行了sleep(long time)方法.

    6:终止状态(terminated)

    通常称为死亡状态,表示线程终止.
            1):正常执行完run方法而退出(正常死亡).
            2):遇到异常而退出(出现异常之后,程序就会中断)(意外死亡).
    -------------------------------------------------------------------
    线程一旦终止,就不能再重启启动,否则报错(IllegalThreadStateException).
    在Thread类中过时的方法(因为存在线程安全问题,所以弃用了):
     void suspend() :暂停当前线程
     void resume()  :恢复当前线程
     void stop()  :结束当前线程


    展开全文
  • | 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...为什么要了解线程生命周期? ...

    | 好看请赞,养成习惯

    • 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想

    • If you can NOT explain it simply, you do NOT understand it well enough

    现陆续将Demo代码和技术文章整理在一起 Github实践精选 ,方便大家阅读查看,本文同样收录在此,觉得不错,还请Star🌟

    为什么要了解线程的生命周期?

    之前写过 Spring Bean 生命周期三部曲:

    1. Spring Bean生命周期之缘起
    2. Spring Bean生命周期之缘尽
    3. Spring Aware 到底是什么?

    有朋友留言说:“了解了它们的生命周期后,使用 Spring Bean 好比看到它们的行动轨迹,现在使用就一点都不慌了”。我和他一样,了解事物的生命周期目的很简单,唯【不慌】也

    Java 并发系列 已经写了很多,从来还没提起过那个它【Java线程生命周期】。有了前序理论图文的铺垫,在走进源码世界之前,谈论它的时机恰好到了。因为,编写并发程序的核心之一就是正确的摆弄线程状态

    线程生命周期的几种状态

    刚接触线程生命周期时,我总是记不住,也理解不了他们的状态,可以说是比较混乱,更别说它们之间是如何进行状态转换的了。原因是我把操作系统通用线程状态编程语言封装后的线程状态 概念混淆在一起了

    操作系统通用线程状态

    个人觉得通用线程状态更符合我们的思考习惯。其状态总共有 5 种 (如下图)。对于经常写并发程序的同学来说,其嘴里经常念的都是操作系统中的这些通用线程状态,且看

    除去生【初始状态】死【终止状态】,其实只是三种状态的各种转换,听到这句话是不是心情放松了很多呢?

    为了更好的说明通用线程状态Java 语言中的线程状态,这里还是先对前者进行简短的说明

    初始状态

    线程已被创建,但是还不被允许分配CPU执行。注意,这个被创建其实是属于编程语言层面的,实际在操作系统里,真正的线程还没被创建, 比如 Java 语言中的 new Thread()。

    可运行状态

    线程可以分配CPU执行,这时,操作系统中线程已经被创建成功了

    运行状态

    操作系统会为处在可运行状态的线程分配CPU时间片,被 CPU 临幸后,处在可运行状态的线程就会变为运行状态

    休眠状态

    如果处在运行状态的线程调用某个阻塞的API等待某个事件条件可用,那么线程就会转换到休眠状态,注意:此时线程会释放CPU使用权,休眠的线程永远没有机会获得CPU使用权,只有当等待事件出现后,线程会从休眠状态转换到可运行状态

    终止状态

    线程执行完或者出现异常 (被interrupt那种不算的哈,后续会说)就会进入终止状态,正式走到生命的尽头,没有起死回生的机会

    接下来就来看看你熟悉又陌生,面试又经常被问到的Java 线程生命周期吧

    Java语言线程状态

    在 Thread 的源码中,定义了一个枚举类 State,里面清晰明了的写了Java语言中线程的6种状态:

    1. NEW
    2. RUNNABLE
    3. BLOCKED
    4. WAITING
    5. TIMED_WAITING
    6. TERMINATED

    这里要做一个小调查了,你有查看过这个类和读过其注释说明吗?(欢迎留言脚印哦)

    耳边响起五环之歌,Java中线程状态竟然比通用线程状态的 5 种多1种,变成了 6 种。这个看似复杂,其实并不是你想的那样,Java在通用线程状态的基础上,有裁剪,也有丰富,整体来说是少一种。再来看个图,注意颜色区分哦

    Java 语言中

    • 将通用线程状态的可运行状态运行状态合并为 Runnable
    • 休眠状态细分为三种 (BLOCKED/WAITING/TIMED_WAITING); 反过来理解这句话,就是这三种状态在操作系统的眼中都是休眠状态,同样不会获得CPU使用权

    看上图右侧【Java语言中的线程状态】,进一步简洁的说,除去线程生死,我们只要玩转 RUNNABLE休眠状态的转换就可以了,编写并发程序也多数是这两种状态的转换。所以我们需要了解,有哪些时机,会触发这些状态转换

    远看看轮廓, 近看看细节。我们将上面Java语言中的图进行细化,将触发的节点放到图中 (这看似复杂的图,其实三句话就能分解的,所以别慌),且看:

    RUNNABLE与BLOCKED状态转换

    当且仅有(just only)一种情况会从 RUNNABLE 状态进入到 BLOCKED 状态,就是线程在等待 synchronized 内置隐式锁;如果等待的线程获取到了 synchronized 内置隐式锁,也就会从 BLOCKED 状态变为 RUNNABLE 状态了

    注意:

    上面提到,以操作系统通用状态来看,线程调用阻塞式 API,会变为休眠状态(释放CPU使用权),但在JVM层面,Java线程状态不会发生变化,也就是说Java线程的状态依旧会保持在 RUNNABLE 状态。JVM并不关心操作系统调度的状态。在JVM看来,等待CPU使用权(操作系统里是处在可执行状态)与等待I/O(操作系统是处在休眠状态),都是等待某个资源,所以都归入了RUNNABLE 状态

    ​ —— 摘自《Java并发编程实战》

    RUNNABLE与WAITING状态转换

    调用不带时间参数的等待API,就会从RUNNABLE状态进入到WAITING状态;当被唤醒就会从WAITING进入RUNNABLE状态

    RUNNABLE与 TIMED-WAITING 状态转换

    调用带时间参数的等待API,自然就从 RUNNABLE 状态进入 TIMED-WAITING 状态;当被唤醒或超时时间到就会从TIMED_WAITING进入RUNNABLE状态

    看图中的转换 API 挺多的,其实不用担心,后续分析源码章节,自然就会记住的,现在有个印象以及知道状态转换的节点就好了


    相信到这里,你看Java线程生命周期的眼神就没那么迷惑了,重点就是RUNNABLE与休眠状态的切换,接下来我们看一看,如何查看线程中的状态,以及具体的代码触发点

    如何查看线程处在什么状态

    程序中调用 getState() 方法

    Thread 类中同样存在 getState() 方法用于查看当前线程状态,该方法就是返回上面提到的枚举类 State

    NEW

    就是上面提到, 编程语言中特有的,通过继承 Thread 或实现 Runnable 接口定义线程后,这时的状态都是 NEW

    Thread thread = new Thread(() -> {});
    System.out.println(thread.getState());

    RUNNABLE

    调用了 start() 方法之后,线程就处在 RUNNABLE 状态了

    Thread thread = new Thread(() -> {});
    thread.start();
    //Thread.sleep(1000);
    System.out.println(thread.getState());

    BLOCKED

    等待 synchronized 内置锁,就会处在 BLOCKED 状态

    public class ThreadStateTest {
    
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(new DemoThreadB());
            Thread t2 = new Thread(new DemoThreadB());
    
            t1.start();
            t2.start();
    
            Thread.sleep(1000);
    
            System.out.println((t2.getState()));
            System.exit(0);
        }
    }
    
    class DemoThreadB implements Runnable {
        @Override
        public void run() {
            commonResource();
        }
    
        public static synchronized void commonResource() {
            while(true) {
    
            }
        }
    }

    WAITING

    调用线程的 join() 等方法,从 RUNNABLE 变为 WAITING 状态

    public static void main(String[] args) throws InterruptedException {
            Thread main = Thread.currentThread();
    
            Thread thread2 = new Thread(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
                System.out.println(main.getState());
            });
            thread2.start();
            thread2.join();
        }

    TIMED-WAITING

    调用了 sleep(long) 等方法,线程从 RUNNABLE 变为 TIMED-WAITING 状态

    public static void main(String[] args) throws InterruptedException {
            Thread thread3 = new Thread(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
            // 为什么要调用interrupt方法?
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            });
            thread3.start();
    
            Thread.sleep(1000);
            System.out.println(thread3.getState());
        }

    TERMINATED

    线程执行完自然就到了 TERMINATED 状态了

    Thread thread = new Thread(() -> {});
    thread.start();
    Thread.sleep(1000);
    System.out.println(thread.getState());

    以上是程序中查看线程,自己写写测试看看状态还好,现实中的程序怎么可能允许你加这么多无用代码,所以,翠花,上酸菜(jstack

    jstack 命令查看

    相信你听说过这玩意,jstack 命令就比较强大了,不仅能查看线程当前状态,还能看调用栈,锁等线程栈信息

    大家可以随意写一些程序,这里我用了上面 WAITING 状态的代码, 修改睡眠时间 Thread.sleep(100000),然后在终端按照下图标示依次执行下图命令

    更多功能还请大家自行查看,后续会单独写文章来教大家如何使用jstack查看线程栈信息

    Arthas

    这个利器,无须多言吧,线上找茬监控没毛病,希望你可以灵活使用这个工具,攻克疑难杂症

    查看线程栈详细信息,非常方便:https://alibaba.github.io/arthas/thread.html

    相信你已经和Arthas确认了眼神

    关于线程生命周期状态整体就算说完了,编写并发程序时多问一问自己:

    调用某个API会将你的线程置为甚么状态?

    多问自己几次,自然就记住上面的图了

    灵魂追问

    1. 为什么调用 Thread.sleep, catch异常后,调用了Thread.currentThread().interrupt();

    2. 进入 BLOCKED只有一种情况,就是等待 synchronized 监视器锁,那调用 JUC 中的 Lock.lock() 方法,如果某个线程等待这个锁,这个线程状态是什么呢?为什么?

      public class ThreadStateTest {
      
          public static void main(String[] args) throws InterruptedException {
              TestLock testLock = new TestLock();
      
              Thread thread2 = new Thread(() -> {
                  testLock.myTestLock();
              }, "thread2");
      
              Thread thread1 = new Thread(() -> {
                      testLock.myTestLock();
                  }, "thread1");
      
              thread1.start();
              Thread.sleep(1000);
      
              thread2.start();
              Thread.sleep(1000);
      
              System.out.println("****" + (thread2.getState()));
      
              Thread.sleep(20000);
          }
      }
      
      @Slf4j
      class TestLock{
          private final Lock lock = new ReentrantLock();
      
          public void myTestLock(){
              lock.lock();
              try{
                  Thread.sleep(10000);
                  log.info("testLock status");
              } catch (InterruptedException e) {
                  log.error(e.getMessage());
              } finally {
                  lock.unlock();
              }
          }
      }
    1. synchronized 和 Lock 有什么区别?

    参考

    感谢前辈们总结的精华,自己所写的并发系列好多都参考了以下资料

    • Java 并发编程实战
    • Java 并发编程之美
    • 码出高效
    • Java 并发编程的艺术
    • ......

    我这面也在逐步总结常见的并发面试问题(总结ing......)答案整理好后会通知大家,请持续关注

    展开全文
  • 线程的五大生命周期 NEW:         线程新建状态 RUNNABLE:     就绪状态 RUNNING:          运行状态 BLOCKED:       堵塞状态 TERMINTED:    终止状态 看完Java...

    关于线程的六个状态可以看一下:Java线程的6个状态
    建议先看一下上面的文章,再看下面的文章。

    线程的五大生命周期
    NEW:         线程新建状态
    RUNNABLE:     就绪状态
    RUNNING:          运行状态
    BLOCKED:       堵塞状态
    TERMINTED:    终止状态

    看完Java线程的6个状态我们会发现五大状态比Thread.state多了一个RUNNING状态,但是少了TIME_WAITINGWAITING两个状态,线程的生命周期把线程的TIME_WAITINGWAITING这两个状态都归入到了BLOCKED状态,接下来说一下RUNNING和RUNNABLE吧,其他的就不重复说了。

    RUNNING就绪状态
    当调用线程对象的start()方法,线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说此线程立即就会执行;
    Running运行状态
    当就绪的线程被调度并获得CPU资源时,此时线程才得以真正执行,即进入到运行状态。就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

    如下图
    在这里插入图片描述
    七种基本基础状态
    其实就是在thread.state的6个状态中加上生命周期的running,就组成了7种基础状态,知识点都一样的哈。
    new
    runnable
    running
    time_waiting
    waiting
    blocked
    terminated

    展开全文
  • 线程的生命周期——Java多线程(3)

    千次阅读 2020-05-31 22:07:52
    线程的六种状态以及相互转化 在线程new xxx().start()之后,并不是立即进入执行状态,我们在java.lang.Thread.state中可以看到有六种状态: 线程状态 发生条件 New 线程被创建,new xxxx(),但是还没有调用....
    线程的六种状态以及相互转化

    在线程new xxx().start()之后,并不是立即进入执行状态,我们在java.lang.Thread.state中可以看到有六种状态:

    线程状态发生条件
    New线程被创建,new xxxx(),但是还没有调用.start()方法
    Runnable线程在jvm中的运行状态
    Block(阻塞)线程为获取到锁对象(资源),线程进入阻塞状态,当线程获取到锁对象(资源),转入Runnable状态
    Time_Wait通过调用带有超时参数的方法进入Time_Wait状态,常用的方法有Thread.sleep() Object.Wait()
    Wait(等待)与Time_Wait区别是超时不会自动唤醒,需要另一个线程主动notify(),或者是NotifyAll()
    Teminated(被 终止)因为Run方法正常退出而死亡,或者是异常未被捕获

    在这里插入图片描述

    展开全文
  • JAVA线程生命周期

    千次阅读 2019-03-05 20:10:51
    线程生命周期中,它要经过创建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)这五种状态。当线程进入运行状态后,它不是一直“霸占”CPU运行,一般的操作系统是采用抢占式的方式来...
  • 多线程生命周期的五种状态

    千次阅读 2018-04-08 09:04:42
    java中的线程生命周期大体可分为5种状态。 1. 新建(NEW):新创建了一个线程对象。 2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中...
  • 线程要经历开始(等待)、运行、挂起和停止四种不同的状态。这四种状态都可以通过Thread类中的方法进行控制。下面给出了Thread类中和这四种状态相关的方法
  • Java多线程(二)、线程的生命周期和状态控制
  • 线程生命周期.png

    2019-09-17 13:47:07
    多线程生命周期图解,一分钟了解线程从生到死全过程,图文并茂,通俗易懂,容易记忆。独家原创。欢迎下载。
  • 多线程--生命周期 状态图

    千次阅读 2017-10-15 16:11:51
     这幅图是在Java 多线程(三) 线程的生命周期及优先级出现过的:  图中是线程运行的基本状态:线程调用start()方法开始后,就进入到可运行状态,随着CPU的资源调度在运行和可运行之间切换;遇到阻塞则进入...
  • GaiaThreadNest 用于线程生命周期控制的多线程应用程序框架。
  • 线程生命周期及状态转换详解

    万次阅读 2018-01-05 10:45:20
    (1)New:创建线程对象后,该线程处于新建状态,此时它不能运行,和其他Java对象一样,仅仅有Java虚拟机为其分配了内存,没有表现出任何线程的动态特征; (2)Runnable:线程对象调用了start()方法后,该线程就...
  • Java线程生命周期与状态切换

    千次阅读 2020-08-05 10:54:55
    前提最近有点懒散,没什么比较有深度的产出。刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程生命周期、状态切换以及线程的上下文切换等等。编写...
  • 线程生命周期(状态)

    千次阅读 2020-06-26 14:49:35
    线程生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞 (Blocked)和死亡(Dead)5种状态。尤其是当线程启动以后,它不可能一直"霸占"着CPU独自 运行,所以CPU需要在线程之间切换,...
  • 听过前面几篇文章的阅读,我们对多线程已经有了大致的了解。世界上的万物都是有规律的,人有生命周期,幼儿期->少年->青年,当然线程也不例外。跟着社长一起来看看线程的生老病死是怎么一回事。 1.
  • 在 Java 初中级面试中,关于线程生命周期可以说是常客了。本文就针对这个问题,通过图文并茂的方式详细说说。 结合上图,线程生命周期大致可分为以下五种状态: NEW- 新建 RUNNABLE- 等待被CPU调度 ...
  • 线程生命周期及五种基本状态

    万次阅读 多人点赞 2018-10-08 10:38:59
    线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点。掌握了上图中的各知识点,Java中的多线程也就基本上掌握了。主要包括...
  • 文章目录多线程一、进程和线程二、线程创建1、继承Thread类1)创建自定义线程类,重写run方法2)测试类,创建自定义线程,调用其start方法来开启线程2、实现Runable接口1)创建自定义类实现Runable接口2)测试类,...
  • 线程的状态,目前网上很文章停留在五种状态的分析,但是经过翻看thread类的源码发现其实6种状态。最近偶然间看到一篇文章,对于6种状态的转换讲的很好,特此转载过来了。 原文链接:总算把线程六种状态的转换说...
  • 1、Java线程具有五中基本状态: 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread thread1 = new MyThread(); 就绪状态(Runnable):当调用线程对象的start()方法[ 如:thread1 .start(); ],...
  • Java多线程生命周期的讲解,很详细,希望能帮到大家
  • 想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态: 新建: 当一个Thread类或其子类的对象被声明并创建时,...
  • 1、进程可以理解成程序的一次执行(即动态的),所以一个程序可以对应一个或个进程(程序的次执行),而一个进程往往包含一个或线程 2、每个进程有独立的地址空间,包含资源。而线程共享进程的资源,可以把...
  • 线程生命周期状态转化图
  • 初学Java多线程线程的生命周期.pdf
  • 1. 线程生命周期 线程生命周期图 新建状态(New) 当线程对象创建后,即进入新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable) 当调用线程对象的start()方法时,线程即进入就绪状态。处于就绪...
  • 简述线程生命周期

    2020-09-03 21:30:12
    线程生命周期包含5个阶段,包括新建,就绪,运行,阻塞,销毁。 新建:就是使用new方法,new出来的线程; 就绪:调用的线程的start()方法后,线程处于等待CPU分配资源阶段,谁先抢到CPU资源,谁开始执行; 运行:...
  • 进程和多线程生命周期

    千次阅读 2020-02-28 12:34:59
    进程和线程 进程 对于操作系统来说,一个任务就是一个进程(Process)。 课本概念:程序的一个执行实例,正在执行的程序等。 内核观点:担当分配系统资源(CPU时间,内存)的实体 所以最后得出: 进程是担当分配系统...
  • C++11线程生命周期

    千次阅读 2018-07-10 00:29:54
    线程也一样,父线程对子线程生命周期有很大的影响。 以下程序启动一个显示其ID的线程。 // threadForgetJoin.cpp #include <iostream> #include <thread> int main() { std::...
  • Java线程生命周期及五种基本状态

    千次阅读 多人点赞 2020-02-06 20:11:39
    一、Java中线程生命周期图 用这张图可以概述大多的线程创建及运行,简单易懂的掌握线程知识!!! 二、线程的五种基本状态 新建状态(New):至今尚未启动的线程的状态。线程刚被创建,但尚未启动。如:Thread t = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 268,464
精华内容 107,385
关键字:

多线程生命周期