首页 > 其他分享 >第十四章《多线程》第2节:线程的生命周期

第十四章《多线程》第2节:线程的生命周期

时间:2023-01-02 17:32:53浏览次数:59  
标签:状态 执行 线程 第十四章 阻塞状态 多线程 CPU 运行

​线程在被创建后会经历多个状态最后直至死亡,这个过程称为线程的“生命周期”。生命周期中包含很多状态,这些状态有:新生、就绪、运行、阻塞和死亡。线程有可能在几种状态之间多次切换,例如线程开始运行后就进入运行状态,但这个线程不能一直独占CPU,系统会通过调度算法使其他线程得到执行机会。正在执行的线程在被换下后就进入了就绪状态,而过一段时间后这个线程又会重新进入运行状态,因此每一个线程都有可能在运行和就绪状态之间多次切换。本小节将详细讲解线程生命周期以及生命周期中的各个状态。

14.2.1新生和就绪状态

Java语言中任何一个事物都可以用对象来表示,因此一个线程也可以用对象来表示。代表线程的类是Thread,每一个Thread类对象都是一个线程。当线程对象刚被创建出来时,这个线程就处于“新生”状态。新生状态的线程对象与其他对象无异,仅仅是一个对象而已,虚拟机并不会执行线程中的任何代码。​

当线程对象调用了start()方法之后,线程就进入了就绪状态。Java虚拟机会为这个线程对象分配相应的资源以便线程能够顺利执行。需要注意:线程在进入就绪状态后并没有开始运行,只是表示这个线程具有了运行的条件,随时可以运行,但何时运行取决于虚拟机的线程调度程序。​

14.2.2运行和阻塞状态

就绪状态的线程被分配了CPU后就进入了运行状态,此时开始执行线程对象中的代码。如果计算机只有一个CPU,那么同一时刻只能有一个线程被执行,而如果计算有多个CPU,那么同一时刻可能会有多个线程并行执行。注意:并发和并行是两个不同的概念,并发指在同一时刻只能有一个线程执行,但多个线程被快速轮换执行,这使得在宏观上具有多个线程同时执行的效果。除线程外,进程也能够并发执行。而并行是指在同一时刻,有多个线程或进程在多个处理器上同时执行。实际上,即使计算机有多个CPU,但只要线程数量比CPU数量多,依然会出现多个线程在同一个CPU上轮换执行的现象。​

当一个线程进入运行状态后,一般都不会一直运行到结束,除非这个线程中的代码非常短,因此在线程运行过程中很可能被中断,这是为了让其他线程有能够执行的机会。线程的调度由虚拟机的调度器所决定,线程调度主要有两种策略:抢占式和协作式。抢占式策略是指系统会给每个可执行的线程一个小时间段来处理任务,当该时间段用完后,系统就会剥夺该线程所占用的CPU,让其他线程获得执行的机会。而协作式策略是指一个线程在执行自己的任务时不允许被中途打断,一定等当前线程将任务执行完毕后才会释放对CPU的占有,因此协作式策略实际上是当前线程主动放弃CPU后其他线程才有执行的机会。大部分计算机的操作系统都采用抢占式的调度策略,但一些小型设备,如手机则可能采用协作式调度策略。​

线程在运行过程中有时会进入阻塞状态,进入阻塞状态的线程不能继续执行,只能暂时等待,此时其他线程就可以获得执行的机会。导致线程进入阻塞状态的原因很多,这些原因大致可以分为三种:​

  • 线程调用自身的sleep()方法进入睡眠状态​
  • 程序调用了线程的suspend()方法将线程挂起​
  • 线程需要等待某些资源或等待其他线程的通知​

在之前章节的程序案例中,多次调用过Scanner的nextInt()方法,在方法执行时需要让用户输入一个整数。用户在完成输入前,线程无法继续运行,只能处于等待输入的状态,这个状态实际上就是阻塞状态。​

线程进入阻塞状态后,在获得运行条件后又会重新进入就绪状态。此处需要强调:处于阻塞状态的线程在获得运行条件时并不是直接进入运行状态,而是先进入就绪状态,之后等待调度器的调度后才能再次进入运行状态。线程脱离阻塞状态的原因主要有:​

  • 线程的sleep()方法执行已经到了时间​
  • 程序调用线程的resume()方法恢复挂起的线程​
  • 线程等到了它需要的资源或其他线程的通知​

从以上所列的几条可以看出:导致线程进入阻塞状态的原因和使线程脱离阻塞状态的原因恰好是相对应的。​

14.2.3死亡状态

线程在执行完自身所有代码,或者是执行代码过程遇到了没有捕获的Exception或Error都会导致线程死亡。实际上,程序员调用线程的stop()方法也能让线程进入死亡状态,但这种方法容易让线程产生死锁,所以不推荐使用。​

前面讲过:线程是相互独立的,所以当主线程进入死亡状态后,其他线程不会受到影响,仍然可以继续运行。程序员可以调用线程对象的isAlive()方法来测试这个线程是否死亡,当线程处于就绪、运行、阻塞三种状态时,该方法将返回true,当线程处于新建、死亡两种状态时,该方法将返回false。当线程死亡后,不能再调用它的start()方法来重新启动它,这样做程序会抛出IllegalThreadStateException异常。实际上,线程的start()方法一旦被调用就不能被调用第二次,因此除新生态的线程都不能调用start()方法。​

线程的生命周期所经历的各种状态可以用图14-1来表示。​

第十四章《多线程》第2节:线程的生命周期_Java

图14-1线程生命周期的各种状态

本文字版教程还配有更详细的视频讲解,小伙伴们可以点击这里观看。

标签:状态,执行,线程,第十四章,阻塞状态,多线程,CPU,运行
From: https://blog.51cto.com/mugexuetang/5983883

相关文章

  • 第十四章《多线程》第3节:创建线程
    ​Java语言中有一个专门表示线程的Thread类,这个类位于java.lang包下,因此在使用这个类时无需引入。Thread的方法定义了线程的基本操作,下面的表14-1展示了Thread类所定义的方......
  • java多线程
    1、线程:进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。 线程不能独立存在,必须依赖进程,在进程中运行每一个进......
  • 静态方法如何调用非静态方法,创建线程的方式
    在静态方法中,new一个类对象,用类对象调用非静态方法第一种方式创建线程publicclassMain{  privateclassMyRunimplementsRunnable{    publicvoid......
  • C#开发的线程池和管理器 - 开源研究系列文章
          上次编写了一个小软件,用于练手及自己的一个小工具集合。今天把其中的线程池和管理器的代码抽取出来,写成一个博文,让需要的朋友能够进行学习和应用。    ......
  • 1.走近Java世界中的线程
    一.基本概念 进程是程序运行的实例。 进程是程序向操作系统申请资源(如内存空间和文件句柄)的基本单位。线程是进程中可独立执行的最小单位。 一个进程中可以包含多个......
  • 04.关于线程你必须知道的8个问题(下)
    今天我们来学习线程中最后4个问题:线程的同步与互斥线程的本质与调度死锁的产生与解决多线程的是与非通过本篇文章,你可以了解到计算机中经典的同步机制--管程,Java线......
  • Python之路【第七篇】:线程、进程和协程
    1.Python线程Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。#!/usr/bin/envpython#-*-coding:utf-8-*-importthreadingimporttime......
  • 网络程序设计 实验3 多人聊天室 流式套接字 多线程编程
    实验3多人聊天室实验目的:通过流式套接字编程,及多线程编程,实现简单的多人聊天室。开发语言与工具:VC实验要求:1.使用MFC编程。2.利用流式套接字编程及多线程编程。3......
  • Linux线程控制
    写在前面我们今天来看线程的知识点,这个博客的内容很多,主要就是为了我们后面的网络做铺垫,最关键的是相比较于进程而言,线程是更加优秀的,我们现在的计算机大多采用的就是线程.......
  • Linux线程互斥
    写在前面这个博客的内容很少,但是很关键,这是我们线程安全相关的内容,里面会涉及到线程互斥和加锁的相关观念,总体而言还是很难的.线程互斥先看一下下面的代码,这里是一切的......