详解java类的生命周期
- 格式:pdf
- 大小:224.83 KB
- 文档页数:7
java的线程的⽣命周期五种状态解释线程的⽣命周期1.线程的状态:在《疯狂java》中介绍了线程有五种状态:新建(new),就绪(Runnable),运⾏(Running),阻塞(Blocked)和死亡(Dead)但是我查看thread源码之后,发现线程的状态有六种:public enum State {NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;}ps:注释太长了我没有下拉下来,各位感兴趣可以去看看2.新建和就绪状态当程序中new了⼀个thread对象的时候,这个线程处于就绪状态,和其他的对象相同,由jvm分配内存,并且初始化成员变量的数值,这个时候这个线程没有表现出来任何线程的动态特性,也没有执⾏线程体当使⽤了start()⽅法之后,线程状态转变为就绪状态,但是还没有运⾏,等待cpu的分配,这个时候是否运⾏取决于jvm中线程调度器的调度对于⼀个thread对象,如果直接使⽤run()⽅法,并不算启动了线程,这个时候运⾏其实是把run()当做普通的⽅法去执⾏下⾯的这个例⼦中,currentThread().getName()返回的是main线程的名字public static class CurThread extends Thread{public int i=0;public void run() {for(int j=0;j<10;j++)System.out.println("I: "+i+++Thread.currentThread().getName());}}public static void main(String[]__){CurThread t=new CurThread();t.run();//System.out.println(t.isAlive());}也就是说实际上,这个时候并不是thread-0去执⾏。
java类型⽣命周期(java⾯试)java的类型⽣命周期-常见的java的⾯试题⽬jjava的类型⽣命周期可以⽤如下⼏个部分表⽰:装载,连接,初始化,卸载如下图装载过程⼤致分为3部分,⾸先,我们应当有⼀个.class⽂件,这个是⼆进制的数据⽂件,⾥⾯含有java类型的信息。
第⼆部,就是将这个⼆进制⽂件解析出对应的java类型。
第三步,是在堆上创建这种类型的对象。
连接过程:连接过程分为三步:⼀:验证,验证就是保证⽂件按照jvm规范,不会导致jvm崩溃,验证期间需要完成的检查包括:检查final不能拥有⼦类,final⽅法不能被覆盖,确保不存在不合理的引⽤等。
(这个地⽅有些不理解,因为检查这些⼯作应当是编译错误,但是出现编译错误是不能编译出class⽂件的,那这种检查实际上是检查⾮法的class⽂件,⽐如⿊客产⽣的class⽂件,⽤于破坏jvm的完整性。
⽽字节码完整性是对类,⽅法是否存在等进⾏相应的校验)准备:准备阶段就是分配内存解析:解析的第⼀步是初始化。
初始化我们需要进⾏相关的研究。
切记:只有⾸次使⽤的时候才会完成类的初始化,⽽⾸次使⽤出现在以下的6种情况,对此我们分别进⾏了相关的测试。
1.创建新实例。
FTest a = new FTest();将调⽤FTest的构造器,完成初始化2.调⽤某个类的静态⽅法FTest.CallF();3.使⽤某个类的静态字段System.out.println(FTest.FI);4.调⽤某些反射⽅法5.初始化改类的⼦类6.当虚拟机启动某个被表明为启动类的类tomcat中指定启动类的时候会进⾏改过程所有类变量的初始化语句和类型的静态初始化构造器都被java编译器收集在⼀起,放到⼀个特殊的⽅法中,成为<clinit>⽅法.4.卸载java类⽣命周期和对象声明周期很相似,虚拟机创建并初始化对象,在程序不在引⽤对象的时候,便执⾏垃圾收集,同样,虚拟机创建并初始化类,在类不在被引⽤的时候便执⾏相应的卸载。
java对象和类的⽣命周期⼀、java对象的⽣命周期java对象的⽣命周期可以分为7个阶段:创建阶段、使⽤阶段、不可视阶段、不可达阶段、可收集阶段、终结阶段、释放阶段。
1、创建阶段java创建⼀个对象的⽅式:(1)使⽤new关键字。
(2)使⽤反射机制。
(3)对象clone。
Object类中存在clone(),但访问权限为protected,因此被clone的类需要实现Cloneable接⼝,将⽅法权限提升为public。
Cloneable只是⼀个标识接⼝。
(4)使⽤序列化。
2、使⽤阶段四类对象引⽤:强引⽤、软引⽤、弱引⽤、虚引⽤。
(1)强引⽤:强引⽤对象⽆论如何都不会被回收。
当出现内存不⾜的情况,宁愿抛出内存溢出(OutOfMemoryError)错误。
(2)软引⽤:具有与强引⽤相同的引⽤功能,只有当JVM出现内存不⾜时,对象会被回收。
(3)弱引⽤:⽆论内存是否充⾜,对象都会被GC回收。
(4)虚引⽤:主要⽤于辅助finalize函数的使⽤,标识那些处于不可达,但是却未被GC回收的对象。
3、不可视阶段对象使⽤已经结束,并且在其可视区域不再使⽤。
此时应主动将对象置为null,有助于JVM及时发现该垃圾对象。
4、不可达阶段JVM通过可达性分析,从root集合中找不到该对象直接或间接的强引⽤。
此时该对象被标注为GC回收的预备对象,但没有被直接回收。
在可达性分析时可作为root的对象: (1)被启动类(bootstrap 加载器)加载的类和创建的对象; (2)栈(本地⽅法栈和java栈)引⽤的对象。
(3)⽅法区中静态引⽤指向的对象。
(4)⽅法区中常量引⽤指向的对象。
5、可收集阶段GC已经发现该对象不可达。
6、终结阶段finalize⽅法已经被执⾏7、释放阶段对象空间已经被重⽤⼆、java类的⽣命周期java类的⽣命周期分为7个阶段:加载、验证、准备、解析、初始化、使⽤、卸载。
(java类声明周期) (类的各个状态)类加载概念:类的加载指的是将.class⽂件的⼆进制数据加载到内存中,将其放置在运⾏时数据区的⽅法区内,然后在堆区创建⼀个ng.Class对象,⽤来封装类在⽅法区内的数据结构。
Java应用程序的生命周期管理在Java开发中,应用程序的生命周期管理是一个至关重要的方面。
通过有效地管理应用程序的生命周期,我们可以确保应用程序的可靠性、稳定性和可扩展性。
本文将介绍Java应用程序的生命周期,并探讨如何管理这些不同阶段。
1. 编码阶段在Java应用程序的生命周期中,编码阶段是第一步。
在这个阶段,开发人员使用Java编程语言编写应用程序的源代码。
在编码过程中,开发人员应该遵循良好的编码实践和设计模式,以确保代码的可读性、可维护性和可测试性。
2. 编译阶段一旦完成了源代码的编写,就需要将其编译为可执行的字节码。
在Java中,使用Java编译器将源代码编译为字节码文件(.class文件)。
编译过程中会检查代码的语法错误和类型错误,以提前捕获并修复潜在的问题。
3. 打包和部署阶段在完成编译后,我们需要将应用程序的字节码和相关资源文件打包成可执行的JAR文件或WAR文件。
JAR文件通常用于独立的命令行应用程序,而WAR文件用于Web应用程序。
打包完成后,应用程序可以被部署到目标环境中,如本地服务器、云平台或分布式系统。
4. 启动阶段启动是应用程序的一个关键阶段。
在这个阶段,Java虚拟机(JVM)会加载应用程序的字节码并执行其入口点方法(例如main方法)。
通过编写适当的启动脚本或配置文件,我们可以自定义启动过程中的参数和选项,以满足特定的需求。
5. 运行阶段一旦应用程序成功启动,它会处于运行状态,即可接收用户的请求并执行相应的操作。
在运行阶段,应用程序可能需要连接数据库、处理用户输入、生成响应等操作。
开发人员应该确保应用程序在运行过程中具有良好的性能和稳定性,以提供良好的用户体验。
6. 关闭阶段当应用程序完成运行或需要关闭时,它会进入关闭阶段。
在关闭阶段,应用程序可以释放资源、保存状态或执行一些清理操作。
开发人员应该编写适当的关闭逻辑,以确保应用程序能够优雅地关闭,并避免资源泄漏或数据丢失。
这一章以一个Java类型(类或接口)的生命周期为例来讨论开始阶段的装载、连接和初始化,以及占Java类型生命周期绝大部分时间的对象实例化、垃圾收集和对象终结,然后是java类型生命周期的结束,也就是从虚拟机中卸载。
7.1、类型装载、连接与初始化Java虚拟机通过装载、连接和初始化一个Java类型,使该类型可以被正在运行的java程序所使用。
其中,类装载就是把二进制形式的Java类型读入Java虚拟机中;而连接就把这种已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去。
连接阶段分为三个子步骤——验证、准备和解析。
“验证”步骤确保了Java类型数据格式正确并且适于Java虚拟机使用。
“准备”步骤则负责为该类型分配它所需的内存,比如为它的类变量分配内存。
“解析”步骤则负责把常量池中的符号引用转换为直接引用。
虚拟机的实现可以推迟解析这一步,它可以在当运行中的程序真正使用某个符号引用时再去解析它。
之后,进行初始化,在初始化期间,都将给类变量赋以适当的初始值。
在类和接口被装载和连接的时机上,java虚拟机规范没有严格的规定,但是它严格的定义了初始化的时机,所有的Java虚拟机实现必须在每个类或接口首次主动使用时初始化。
下面六种情况符合主动使用的要求:1)、当创建某个类的实例时(通过new指令或通过不明确的创建、反射、克隆、反序列化)2)、当调用某个类的静态方法时3)、当使用某个类或接口的静态字段,或者对该字段赋值时。
(final修饰的静态字段除外,它被初始化为一个编译时的常量表达式)4)、当调用Java API中的某些反射方法时,比如类Class中的方法或者ng.reflect 包中的类的方法5)、当初始化某个类的子类时(某个类初始化时,要求它的超类已经被初始化了)6)、当虚拟机启动时某个被标明为启动类(即含有main()方法的那个类)注:任何一个类的初始化都要求它的所有祖先类预先初始化,而一个接口的初始化,并不要求它的祖先接口预先被初始化。
线程的⽣命周期及五种基本状态我们知道线程是操作系统能够进⾏运算调度的最⼩单位,在java中的线程其实就是对操作系统的中的线程进⾏了封装。
我们今天就来说说Java线程的⽣命周期,也就线程的⽣⽼病死!Java的线程⽣命周期有六种状态:New(初始化状态)Runnable(就绪状态)Running(运⾏状态)Blocked(阻塞状态)Terminated(终⽌状态)1.New(初始化状态):当线程对象对创建后,即进⼊了新建状态,如:Thread t = new MyThread();2.Runnable(就绪状态):当调⽤线程对象的start()⽅法,线程即进⼊就绪状态。
处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执⾏,并不是说执⾏了start()此线程⽴即就会执⾏;3.Running(运⾏状态):当就绪状态中的线程获得了CUP执⾏资源,执⾏run()中的代码,这样的线程我们称为运⾏状态的线程。
4.Blocked(阻塞状态):处于运⾏状态中的线程由于某种原因,暂时放弃对CPU的使⽤权,停⽌执⾏,此时进⼊阻塞状态,直到其进⼊到就绪状态,才有机会再次被CPU调⽤以进⼊到运⾏状态。
线程的阻塞状态分为两种:第⼀种,Waiting(⽆时间限制的等待状态):这个状态下是不能分配CPU执⾏的。
有三种情况会使得Running状态到waiting状态调⽤⽆参的Object.wait()⽅法。
等到notifyAll()或者notify()唤醒就会回到Runnable状态。
调⽤⽆参的Thread.join()⽅法。
也就是⽐如你在主线程⾥⾯建⽴了⼀个线程A,调⽤A.join(),那么你的主线程是得等A执⾏完了才会继续执⾏,这是你的主线程就是等待状态。
调⽤LockSupport.park()⽅法。
LockSupport是Java6引⼊的⼀个⼯具类Java并发包中的锁都是基于它实现的,再调⽤LocakSupport.unpark(Thread thread),就会回到Runnable状态。
软件工程开发生命周期详解软件工程开发生命周期是指软件项目从开始到结束的一系列阶段和过程。
它被广泛应用于软件开发过程中,以确保项目的成功完成。
本文将详细介绍软件工程开发生命周期的各个阶段和其重要性。
1. 需求分析阶段需求分析是软件工程开发生命周期中的关键步骤之一。
在这个阶段,软件开发团队与客户合作,明确软件项目的需求和目标。
此阶段通常包括以下步骤:- 收集客户需求:与客户沟通,了解他们的期望和要求。
- 分析需求:评估收集到的需求,确定项目的范围和功能。
- 编写需求文档:将需求文档编写为可供开发团队参考的形式。
2. 设计阶段在需求分析阶段完成后,软件开发团队将开始进行设计工作。
这一阶段的目标是创建一个详细的软件设计方案,以指导开发人员的实际编码工作。
常见的设计任务包括:- 系统设计:确定软件系统的整体架构和组件之间的关系。
- 模块设计:设计每个模块的详细功能和逻辑。
- 数据库设计:设计数据库结构和数据存储方案。
3. 编码阶段编码阶段是将设计文档转化为实际可执行代码的过程。
在这个阶段,开发人员将使用选择的编程语言和开发工具来实现软件系统的功能。
主要任务包括:- 编写源代码:根据设计文档编写代码,实现系统功能。
- 进行单元测试:对编写的代码进行单元测试,确保代码质量和功能的正确性。
4. 测试与验证阶段测试与验证阶段旨在确保软件系统达到预期的质量标准。
在该阶段,测试人员将使用各种测试技术和工具来检查系统的正确性、性能和安全性。
以下是常见的测试类型:- 功能测试:验证软件系统是否按照需求规范工作。
- 性能测试:评估系统在不同负载下的性能表现。
- 安全测试:检查软件系统的安全性,发现潜在的漏洞和风险。
5. 部署与维护阶段在测试与验证阶段完成后,软件系统准备好部署到实际的生产环境中。
这一阶段还包括软件的维护和升级。
主要任务包括:- 部署软件系统:将软件系统安装到目标服务器或计算机上。
- 运行系统测试:验证部署后的系统在实际环境中能否正常工作。
java线程的生命周期创建Java线程在Java程序中创建线程有几种方法。
每个Java程序至少包含一个线程:主线程。
其它线程都是通过Thread构造器或实例化继承类Thread的类来创建的。
Java线程可以通过直接实例化Thread对象或实例化继承Thread的对象来创建其它线程。
在线程基础中的示例(其中,我们在十秒钟之内计算尽量多的素数)中,我们通过实例化CalculatePrimes类型的.对象(它继承了Thread),创建了一个线程。
当我们讨论Java程序中的线程时,也许会提到两个相关实体:完成工作的实际线程或代表线程的Thread对象。
正在运行的线程通常是由操作系统创建的;Thread对象是由JavaVM创建的,作为控制相关线程的一种方式。
创建线程和启动线程并不相同在一个线程对新线程的Thread对象调用start()方法之前,这个新线程并没有真正开始执行。
Thread对象在其线程真正启动之前就已经存在了,而且其线程退出之后仍然存在。
这可以让您控制或获取关于已创建的线程的信息,即使线程还没有启动或已经完成了。
通常在构造器中通过start()启动线程并不是好主意。
这样做,会把部分构造的对象暴露给新的线程。
如果对象拥有一个线程,那么它应该提供一个启动该线程的start()或init()方法,而不是从构造器中启动它。
(请参阅参考资料,获取提供此概念更详细说明的文章链接。
)结束Java线程Java线程会以以下三种方式之一结束:Java线程到达其run()方法的末尾。
Java线程抛出一个未捕获到的Exception或Error。
另一个Java线程调用一个弃用的stop()方法。
弃用是指这些方法仍然存在,但是您不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。
当Java程序中的所有线程都完成时,程序就退出了。
加入Java线程ThreadAPI包含了等待另一个线程完成的方法:join()方法。
类的⽣命周期类⽣命周期概况JVM为java程序提供运⾏时环境(runtime environment),管理类和对象的⽣命周期是JVM的重要⼯作之⼀。
类的⽣命周期从类被加载、连接和初始化开始到类被卸载结束。
只有当类在⽣命周期中时,才能被使⽤,⽐如调⽤类的静态⽅法或者创建类的实例。
类的加载、连接和初始化类的⽣命周期从加载、连接和初始化开始。
并且严格按照如下步骤进⾏:1. 加载:查找,并且加载类的⼆进制数据2. 连接 1. 验证:确保类被正确加载 2. 准备:为类的静态变量分配内存,并且初始化为默认值 3. 解析:把类中的符号引⽤转化为直接引⽤3. 初始化:为类的静态变量赋予正确的初始值。
加载类加载的过程如下:1. 将类对应.class⽂件中的⼆进制数据读到内存中,把它存放在运⾏时数据区的⽅法区内;2. 在堆区创建⼀个Class实例,此实例 a) 描述了⽅法区内的数据结构 b) 提供了访问类在⽅法区内数据结构的接⼝,如下图所⽰:可以简单的理解为:类加载的产品是⼀个Class类的实例。
连接连接指将已经读⼊内存的⼆进制数据合并到虚拟机的运⾏时环境中去。
包括验证、准备、解析三个步骤。
验证被加载的.class⽂件并不⼀定是java编辑器⽣成的(⽐如⿊客可以制作⾃定义结构的.class⽂件),所以jvm才需要对.class⽂件进⾏验证,保证被加载的类有正确的内部结构,并且与其他类协调⼀致。
如果jvm检查到错误,那么抛出Error对象。
以此来提⾼程序的健壮性。
准备准备阶段为类的静态变量分配内存并且赋默认值。
解析解析阶段,jvm把类的⼆进制数据中的符号引⽤替换为直接引⽤。
⽐如,dog.run();这⾏代码,run这个⽅法是被dog这个符号(变量名)引⽤,解析过程将dog这个符号替换为⼀个指针地址(直接引⽤)。
初始化执⾏指静态变量⽣命和静态代码块。
卸载当类被加载、连接、初始化后,⽣命周期就开始了,java程序可以正常使⽤该类(实例化,调⽤⽅法等),当描述此类的Class对象不可触及(触不可及为对象⽣命周期中的概念),Class对象将结束⽣命周期,此类⽅法区内的数据将被卸载,此类的⽣命周期结束。
java线程⽣命周期以及start源码剖析(模板⽅法)线程⽣命周期(状态)当线程被创建并启动以后,它既不是⼀启动就进⼊了执⾏状态,也不是⼀直处于执⾏状态。
在线程的⽣命周期中,它要经过新建(New)、就绪(Runnable)、运⾏(Running)、阻塞 (Blocked)和死亡(Dead)5 种状态。
尤其是当线程启动以后,它不可能⼀直"霸占"着 CPU 独⾃运⾏,所以CPU 需要在多条线程之间切换,于是线程状态也会多次在运⾏、阻塞之间切换新建状态(NEW)当程序使⽤ new 关键字创建了⼀个线程之后,该线程就处于新建状态,此时仅由 JVM 为其分配内存,并初始化其成员变量的值就绪状态(RUNNABLE)当线程对象调⽤了 start()⽅法之后,该线程处于就绪状态。
Java 虚拟机会为其创建⽅法调⽤栈和程序计数器,等待调度运⾏。
运⾏状态(RUNNING)如果处于就绪状态的线程获得了 CPU,开始执⾏ run()⽅法的线程执⾏体,则该线程处于运⾏状态。
阻塞状态(BLOCKED)阻塞状态是指线程因为某种原因放弃了 cpu 使⽤权,也即让出了 cpu timeslice,暂时停⽌运⾏。
直到线程进⼊可运⾏(runnable)状态,才有机会再次获得 cpu timeslice 转到运⾏(running)状态。
阻塞的情况分三种:等待阻塞(o.wait->等待对列)运⾏(running)的线程执⾏ o.wait()⽅法,JVM 会把该线程放⼊等待队列(waitting queue) 中。
同步阻塞(lock->锁池)运⾏(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占⽤,则 JVM 会把该线程放⼊锁池(lock pool)中。
其他阻塞(sleep/join)运⾏(running)的线程执⾏ Thread.sleep(long ms)或 t.join()⽅法,或者发出了 I/O 请求时, JVM 会把该线程置为阻塞状态。