zoukankan      html  css  js  c++  java
  • 线程的生命周期?什么时候会出现僵死进程?

    线程的生命周期及五种基本状态

    关于Java中线程的生命周期,首先看一下下面这张较为经典的图:
    

    线程生命周期

    • 新建(new Thread)

    当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。例如:Thread t1=new Thread();

    • 就绪(runnable)

    调用Thread类的start方法,线程已经被启动,进入就绪状态,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。

    • 运行(running)

    线程获得CPU资源正在执行任务(执行run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束或者时间片结束。

    • 堵塞(blocked)

    由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。阻塞结束后线程进入就绪状态。
    堵塞的情况分三种:

    (一)等待堵塞:执行的线程执行wait()方法,JVM会把该线程放入等待池中。

    (二)同步堵塞:执行的线程在获取对象的同步锁时,若该同步锁被别的线程占用。则JVM会把该线程放入锁池中。

    (三)其它堵塞:执行的线程执行sleep()或join()方法,或者发出了I/O请求时。JVM会把该线程置为堵塞状态。
    当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完成时。线程又一次转入就绪状态。

    • 死亡(dead)

      当线程执行完毕(run方法运行结束)或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

    线程间的状态转换

    链接url
    线程间的状态转换

    • 解释:

      1、线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但无论如何,当我们new了这个对象后。线程就进入了初始状态;
      2、当该对象调用了start()方法,就进入可执行状态; 3、进入可执行状态后,当该对象被操作系统选中。获得CPU时间片就会进入执行状态;
      4、进入执行状态后情况就比較复杂了
      4.1、run()方法或main()方法结束后,线程就进入终止状态;
      4.2、当线程调用了自身的sleep()方法或其它线程的join()方法,就会进入堵塞状态(该状态既停止当前线程,但并不释放所占有的资源)。当sleep()结束或join()结束后。该线程进入可执行状态,继续等待OS分配时间片;
      4.3、线程调用了yield()方法,意思是放弃当前获得的CPU时间片,回到可执行状态,这时与其它进程处于同等竞争状态,OS有可能会接着又让这个进程进入执行状态。

      4.4、当线程刚进入可执行状态(注意,还没执行),发现将要调用的资源被synchroniza(同步),获取不到锁标记。将会马上进入锁池状态,等待获取锁标记(这时的锁池里或许已经有了其它线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入可执行状态。等待OS分配CPU时间片。

      4.5、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的全部资源,与堵塞状态不同)。进入这个状态后。是不能自己主动唤醒的,必须依靠其它线程调用notify()或notifyAll()方法才干被唤醒(因为notify()仅仅是唤醒一个线程,但我们由不能确定详细唤醒的是哪一个线程。或许我们须要唤醒的线程不可以被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池。等待获取锁标记。

    一个线程会因为以下原因而放弃CPU:

    1. 时间片用完了,java虚拟机让当前线程暂时放弃CPU,转到就绪状态,使其它线程获得运行机会。

    2. 当前线程因为某些原因而进入阻塞状态

    3. 线程结束运行

    线程在以下情况会停止:

    1. run方法正常执行完毕

    2. run方法执行过程中抛出一个未捕获的异常

    3. 调用stop方法(不推荐使用)

    进程的停止,当一个进程中所有的前台线程停止后,该进程结束。

    如果希望明确地让一个线程给另外一个线程运行的机会,可以采取以下办法。
    1. 调整各个线程的优先级
    2. 让处于运行状态的线程调用Thread.sleep()方法
    3. 让处于运行状态的线程调用Thread.yield()方法
    4. 让处于运行状态的线程调用另一个线程的join()方法

  • 相关阅读:
    通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[中]:管道如何处理请求
    通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[上]:采用管道处理请求
    .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”
    [WCF]缺少一行代码引发的血案
    如何利用ETW(Event Tracing for Windows)记录日志
    .NET Core的日志[5]:利用TraceSource写日志
    .NET Core的日志[4]:将日志写入EventLog
    .NET Core的日志[3]:将日志写入Debug窗口
    .NET Core的日志[2]:将日志输出到控制台
    .NET Core采用的全新配置系统[10]: 配置的同步机制是如何实现的?
  • 原文地址:https://www.cnblogs.com/inyu/p/13659069.html
Copyright © 2011-2022 走看看