




已阅读5页,还剩264页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java2面向对象程序设计基础 中 第5章包 接口和异常第6章线程第7章输入与输出第8章Java的网络编程 第5章包 接口和异常 时间 3次课 6学时 第5章包 接口和异常 教学提示 Java将相关的类组成包 有助于大型软件系统的管理 接口的设计和调用也是Java程序设计的重要技术 对各种异常的处理是程序设计中要解决的重要问题 Java采用了一种特殊的机制来处理异常 本章主要介绍 和类相关的两个概念 包 接口 同时在最后还将介绍Java对异常的处理方法 第5章包 接口和异常 5 1包5 2接口5 3异常及其处理5 4创建自定义的异常5 5课后练习 5 1包 5 1 1Java包的用途5 1 2访问包成员5 1 3源文件的布局5 1 4classpath参数 5 1包 尽管类具有强大的功能 但仅仅一个类或少量的几个类根本无法满足应用程序的需要 通常的应用程序可能需要几十个类 复杂的应用程序需要上百个 甚至更多的类 Java将相关的类组成包 有助于大型软件系统的管理 5 1 1Java包的用途 1 包的建立方法Java包通过package语句建立 基本语法是 package 子包名 例如 packagecn edu jmu graphics 在定义类或接口的源文件开始处 通过package语句 可以将相应的类或接口放入package所声明的包里 包是相关类和接口的集合 提供了访问级别控制和命名空间管理 5 1 1Java包的用途 2 包的使用方法每个源文件只能有一个包声明 并且一定要求放在源文件的开始位置 如果一个源文件没有包语句 则源文件所定义的类或接口被系统放入默认包中 包有层次 层次间由点分隔 通过创建和使用包 程序员不仅可以很容易地确定哪些类和接口是相关的 也可以很容易地找到提供特定功能的类和接口 例如 与画图有关的类和接口在graphics包中 5 1 1Java包的用途 3 包的访问权限通过声明类的访问级别 可以控制对类的访问权限 类的访问级别分为默认级和public级 定义类的默认访问级别不需要任何关键字 被声明为默认级的类只对同一个包中的类是可视的 也就是说 只有同一个包内的类实例可以访问这个类 外界不能访问它 如果用关键字public定义类 不但同一个包里的其他类可以访问这个类 其他包中的类也可以访问它 换句话说 同一个包中的类 相互之间有不受限制的访问权限 而在不同包中 只有public类可被访问 5 1 1Java包的用途 除public修饰符之外 用于访问控制的修饰符还有protected和private protected或private仅用来定义方法或变量的访问控制级别 protected方法或protected变量仅对同一个包内的类或不同包中的子类来说是可视的 private方法和private变量对外部定义的类均不可视 表5 1表示了访问控制修饰符的使用范围和相应访问级别 需要说明的是 通常不建议采用默认方式定义方法或成员变量的访问级别 5 1 1Java包的用途 表5 1访问控制表 5 1 1Java包的用途 4 包的命名方式包提供了新的命名空间 既使所定义的类使用与其他包中的类相同的名字 只要同名类所属的包不同名 就不会引起冲突 原因是这些类的全程限定名称不同 类的全程限定名包含了类的各层包名 这实质上是应用了面向对象的概念 将类封装入包中 Java建议反转Internet域名为包名 如域名为 包命名可以cn edu jmu开始 例如建立包cn edu jmu timer 创建类cn edu jmu timer Time 5 1 2访问包成员 对于包来说 只有它的public成员可被外界访问 若外界想要访问包的public类 有3种方式可以实现 1 通过类的全程限定名访问该类 2 通过import语句导入该类 3 通过import语句导入整个包 如果某个类只被访问一次 那么可以直接使用类的全名 5 1 2访问包成员 虽然可以用import语句导入一个包 但是否可以访问包中的类 还取决于该类的访问级别 需要再次强调的是 只有包的public成员才对外界是可视的 参见表5 1 为了方便程序员开发 Java运行时系统自动导入3个完整的包 1 默认包 默认包没有名字 2 java lang包 3 当前所用 5 1 3源文件的布局 Java平台依靠分级文件系统管理Java源文件和字节码文件 Java源文件是以 java为扩展名的文本文件 每个源文件称为一个编译单元 每个编译单元中有一个或者多个类 但至多只能有一个public类 并且源文件必须与public类同名 源文件存放的文件目录映射着相应类所属的包 例如 类Rectangle的文件名Rectangle java 这个文件将被放置在名为graphics的子目录下 graphics目录可以存在于文件系统的任意位置 如图5 1所示 5 1 3源文件的布局 图5 1Rectangle java源文件的目录 5 1 3源文件的布局 如果依据Java的习惯 以反转的域名定义包的名字 如 cn edu jmu graphics Graphic类 源文件名为Graphic java 其源文件目录如图5 2所示 源文件经编译之后产生字节码文件 与源文件同名 扩展名为 class 如图5 3所示 按照好的编程习惯 应该将 java文件和 class文件分列在两个相互对应的目录结构下 如图5 4所示 5 1 3源文件的布局 图5 2Graphic java源文件的目录 5 1 3源文件的布局 图5 3 java文件和 class文件 5 1 3源文件的布局 图5 4java文件和 class文件的布局 5 1 3源文件的布局 以这样的模式组织源文件和字节码文件 有益于Java的编译器和解释器确定用户程序中所用到的类和接口的位置 编译器在编译程序时必须能够准确找到程序中出现的类 并对这些类进行类型匹配和语法检查等工作 同样的道理 解释器在运行程序时也必须能够确定相应的字节码文件的位置 以调用这些类的方法 通过设置classpath环境变量可以帮助编译器和解释器确定类或接口的源文件以及字节码文件的位置 5 1 4classpath参数 classpath参数用于设置Java包所存在的顶级目录 也就是说 通过classpath可以为Java包建立所依存的目录列表 编译和运行Java程序时 系统会自动从classpath环境变量中读取包所在的目录 文件所在目录由系统通过classpath中的目录和package语句定义的目录合成 5 1 4classpath参数 例5 2 下面通过一个完整的实例程序说明classpath参数的作用 同时展示源文件和字节码文件的一种建议布局模式 本例包含两个类Time和TestTime TestTime为主类 程序对用户输入的表示小时 分钟和秒钟的3个整型数 经过数据正确性验证 分别转换为通用时间表示格式和标准时间表示格式 通过对话框显示给用户 运行结果如图5 5所示 5 1 4classpath参数 图5 5运行结果 例5 2 5 1 4classpath参数 文件布局方式如下 创建D JavaSample目录存放Java程序 创建D JavaSample src子目录存放源文件 创建D JavaSample class子目录存放编译后的字节码文件 具体实现方式是将文件TestTime java存放在D JavaSample src子目录下 为使src子目录的结构与class子目录结构相对应 创建D JavaSample src cn edu jmu timer子目录存放Time java文件 类Time和类TestTime的布局如图5 6所示 5 1 4classpath参数 图5 6Time类和TimeTest类的布局 5 1 4classpath参数 Time java中的语句 packagecn edu jmu timer 将Time类放入包cn edu jmu timer中 源文件Time java存放在与包相对应的目录结构下 在TestTime java中通过语句 importcn edu jmu timer Time 导入Time类 需要设置classpath参数 规定程序中的包cn edu jmu timer编译所依存的顶级目录为D JavaSample class 如 setclasspath D JavaSample class 编译 javac dd JavaSample classd JavaSample src cn edu jmu timer Time javajavac dd JavaSample classd JavaSample src TestTime java运行 javaTestTime 5 1 4classpath参数 用户输入的时 分 秒数 分别转换为通用时间格式和标准时间格式 通过对话框显示给用户 运行结果如图5 5所示 现给出这两个Java文件的源代码 Time javapackagecn edu jmu timer importjava text DecimalFormat 用于数据格式化 24小时制时间publicclassTimeextendsObject privateinthour 0 23privateintminute 0 59privateintsecond 0 59 Time类构造器 初始化每个实例对象的值为0 确保每个Time对象处于一致的状态 5 1 4classpath参数 publicTime setTime 0 0 0 数据的正确性验证 对无效数据取0值publicvoidsetTime inth intm ints hour h 0 5 1 4classpath参数 将标准时间格式转换为字符串publicStringtoString DecimalFormattwoDigits newDecimalFormat 00 return hour 12 hour 0 12 hour 12 twoDigits format minute twoDigits format second hour 12 AM PM TestTime java TestTime类需要导入Time类importJavax swing JOptionPane importcn edu jmu timer Time import语句导入Time类publicclassTestTime publicstaticvoidmain Stringargs 5 1 4classpath参数 Timet newTime t setTime 13 27 06 Stringoutput Universaltimeis t toUniversalString nStandardtimeis t toString JOptionPane showMessageDialog null output PackagingClassTime1forReuse JOptionPane INFORMATION MESSAGE System exit 0 5 1 4classpath参数 特别要强调的是 如果没有正确设置classpath参数 那么TestTime java在编译时会出现找不到Time类的错误 Java编译器严格按照classpath和包名所指定的路径寻找包 只要指定的路径下没有所需要的文件 即使该文件就在当前目录 Java也会报告文件找不到的错误 这点对初学者来说需要特别注意 5 2接口 5 2 1接口能够解决的问题5 2 2接口的定义5 2 3Comparable接口5 2 4回调 5 2接口 接口是和类很相似而又有区别的一种结构 接口的设计和调用也是Java程序设计的重要技术 从结构上 接口有如下特点 1 接口用关键字interface来定义 而不是用class 2 接口中定义的变量全是最终的静态变量 3 接口中没有自身的构造方法 而且定义的其他方法全是抽象方法 即只提供方法的定义 而没有提供方法的实现语句 4 接口采用多重继承机制 而不是采用类的单一继承机制 5 2 1接口能够解决的问题 当类只从一个类继承时称为单继承 Java语言只允许单继承 如果需要多继承关系 可以通过Java语言中的接口实现 抽象方法只有方法定义 没有方法体 如果一个类包含任何抽象方法 包括直接的和继承所得 则这个类必须是抽象的 如果一个类是抽象的 则不能创建此类的对象 抽象类强制要求它的所有子类重写自己的方法以覆盖抽象方法 如果存在超类Animal 显然Cat同时具有Animal和Pet的特性 就是说Cat不只是一个Animal 还是一个Pet 除需要继承Animal类 还期望能实现Pet类 因为Java只允许单继承 Cat不能既继承Animal又继承Pet 解决问题的方法是定义接口 并通过接口实现多继承 5 2 2接口的定义 1 接口声明一个完整的接口声明如下 public interfaceinterfaceName extendslistOfSuperInterface 在接口声明中 只有关键字interface和接口名是必需的 其他内容是可选的 public用来指明任意一个类都可以调用此接口 如果一个接口声明中没有关键字public 那么只有那些与本接口在同一个包中的类才能访问它 5 2 2接口的定义 2 接口体接口体包含常量定义和方法定义两部分 常量定义和变量定义在形式上类似 但常量名要求用大写字母表示 其格式如下 typeNAME value 其中 type可以是Java的任何一种数据类型 接口中的常量全都默认为是final和static属性 即使常量定义中没有注上这两个字也是如此 但有些程序中为了使可读性好 仍然写明finalstatic属性 5 2 2接口的定义 方法的定义格式如下 returnTypemethodName para1 para2 其中 returnType表示返回值类型 如果没有返回值 则用关键字void指明 后面方括号中的内容是可选的 用来列出入口参数 入口参数可能有多个 之间用逗号隔开 如果没有入口参数 则可省去这部分内容 由于接口中都用抽象方法 即只对方法作定义而不提供方法的实现语句 所以 接口的方法定义中没有方法体 接口中所有的方法都默认为是abstract属性 5 2 2接口的定义 上述程序段定义了一个接口Bigable 内含一个常量SUM 另外包含3个方法 每个方法都指明了其返回值类型 但接口的方法中没有方法体 例5 5 对接口中定义的方法进行实现 例子详见书141 143页 运行结果如图5 8所示 5 2 2接口的定义 图5 8运行结果 例5 5 5 2 3Comparable接口 经常需要对数据集合中的对象进行比较 若要比较对象 需要实现java lang Comparable接口 Comparable接口具有惟一的方法compareTo Object 其定义为 publicinterfaceComparable publicintcompareTo Objecto 5 2 3Comparable接口 实现Comparable接口的类的所有实例对象之间应该互相可比较 并具备全序关系 这种全序关系采用类的自然排序规则 在Java2中有包括Character File Long ObjectStreamField Short String Float Integer Byte Double BigInteger BigDecimal Date CollationKey在内的23个类实现了Comparable接口 表5 2为其中8种基本数据类型的自然排序规则 虽然有一些类共用同一种自然排序规则 但只有相互可比较的类才能进行排序 5 2 3Comparable接口 表5 2基本数据类型的自然排序规则 5 2 4回调 软件模块之间总是存在着一定的接口 通过接口形成相互调用关系 习惯上 常把调用者称为客户方 被调用者称为服务方 从调用方式上 可以把它们分为三类 同步调用 回调和异步调用 如图5 9所示 其中A表示客户方 B表示服务方 5 2 4回调 图5 9软件接口间的三种调用方式 5 2 4回调 同步调用是一种阻塞式调用 客户方要等待服务方执行完毕才返回 它是一种单向调用 回调是一种双向调用模式 也就是说 服务方在被调用时也会调用客户方 异步调用是一种类似消息或事件的机制 不过它的调用方向刚好相反 服务方在收到某种信息或发生某种事件时 会主动通知客户方 即通过接口调用客户方 5 3异常及其处理 5 3 1什么是异常5 3 2异常的层次结构5 3 3异常的处理 5 3异常及其处理 对各种异常的处理是程序设计中要解决的重要问题 Java采用了一种特殊的机制来处理异常 本节讲述这种机制的思想 并结合具体例子讲解Java怎样用try catch finally语句实现这种机制 最后 简要说明怎样自定义异常类型以扩充Java系统的异常处理功能 5 3 1什么是异常 用任何一种计算机语言设计的程序在运行时都可能出现各种错误 常见的错误如除数为0 文件不存在 文件不能打开 数组下标超过界限 内存不够用等 对于这种在运行中出现的错误 计算机系统中通常有两种处理办法 由计算机系统本身直接检测程序错误 遇到错误时使程序终止运行 由程序员在程序设计中兼顾错误检测 错误信息显示和出错处理 在Java程序中 异常一般由以下两种原因引起 1 程序中存在非法操作 最简单的例子就是除数为0的除法操作 这种原因常常是程序员出于无意或大意造成的 所以称为隐式异常 2 程序员在程序中使用了throw语句引起的异常 5 3 2异常的层次结构 Java程序中的异常以类的层次结构组织 Throwable是所有异常类的父类 它是Object的直接子类 Exception和Error是Throwable的直接子类 而RuntimeException是Exception的子类 在系统包java lang java util java io和中声明的异常类是标准异常类 这些标准异常类分为两种 一种是RuntimeException子类 因为RuntimeException是不可检测的异常类 所以这些标准异常类也是不可检测的异常类 另一种是除了RuntimeException子类以外的其他Exception的子类 这些异常类是可检测的 5 3 2异常的层次结构 1 不可检测的标准异常类 1 java lang中的标准异常类ArithmeticException 表示遇到了异常的算术问题 例如被0整除 ArrayStoreException 试图把与数组类型不相符的值存入数组 ClassCastException 试图把一个对象的引用强制转换为不合适的类型 IndexOutOfBoundsException 下标越界 NullPointerException 试图使用一个空的对象引用 SecurityException 检测到了违反安全的行为 5 3 2异常的层次结构 2 java util中的标准异常类EmptyStackException 试图访问一个空堆栈中的元素 NoSuchElementException 试图访问一个空向量中的元素 2 可检测的标准异常类 1 java langClassNotFoundException 具有指定名字的类或接口没有被发现 CloneNotSupportedException 克隆一个没有实现Cloneable接口的类 IllegalAccessException 试图用给出了完整的路径信息的字符串加载一个类 但是当前正在执行的方法无法访问指定类 因为该类不是public类型或在另一个包中 5 3 2异常的层次结构 InstantiationException 试图使用Class的newInstance方法创建一个对象实例 但指定的对象没有被实例化 因为它是一个接口 抽象类或者一个数组 InterruptedException 当前的线程正在等待 而另一个线程使用了Thread的interrupt方法中断了当前线程 2 java ioIOException 申请I O操作没有正常完成 EOFException 在输入操作正常结束前遇到了文件结束符 FileNotFoundException 在文件系统中 没有找到由文件名字符串指定的文件 InterruptIOException 当前线程正在等待I O操作完成 而另一个线程使用Thread的interrupt方法中断了当前线程 5 3 2异常的层次结构 当一个异常被抛出 即产生了异常 时 应该如何处理呢 在Java语言中 使用语句try catch finally进行异常处理 程序流程从引起异常的代码转移到最近的try语句的catch子句 语句如下所示 try 被监视的代码段 一旦发生异常 则交由其后的catch代码段处理catch 异常类型e catch 异常类型e finally 最终处理 5 3 2异常的层次结构 把可能会发生异常情况的代码放在try语句段中 利用try语句对这组代码进行监视 如果发生了异常 就交由catch语句处理 catch语句在执行前 必须识别抛出的异常是否为catch能够捕获的异常 如果catch语句参数中声明的异常类与抛出的异常类相同 或者是它的父类 catch语句就可以捕获任何这种异常类的对象 5 3 2异常的层次结构 如果希望在异常发生时能确保有一段代码被执行 那么应该使用finally子句 这样即使发生的异常与catch所能捕获的异常不匹配也会执行finally子句 例5 8 使用finally举例 程序如下 publicclassCatchDemo publicstaticvoidmain Stringargs System out println 这是一个异常处理的例子 n try inti 10 i 0 catch ArithmeticExceptione System out println 异常是 e getMessage finally System out println finally语句被执行 5 3 2异常的层次结构 在JCreator中运行结果如图5 10所示 图5 10运行结果 例5 8 5 3 3异常的处理 1 异常的捕获在5 3 2节的例子中 已经用了try catch finally语句块 下面介绍try catch finally语句各部分的用法 捕获异常是通过try catch finally语句实现的 try catch ExceptionName1e catch ExceptionName2e finally 1 try捕获异常的第一步是用try 选定捕获异常的范围 由try所限定的代码块中的语句在执行过程中可能会生成异常对象并抛出 2 catch每个try代码块可以伴随一个或多个catch语句 用于处理try代码块中所生成的异常事件 catch语句只需要一个形式参数指明它所能够捕获的异常类型 这个类必须是Throwable的子类 运行时系统通过参数值把被抛出的异常对象传递给catch块 5 3 3异常的处理 3 finally捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口 使得在控制流转到程序的其他部分以前 能够对程序的状态作统一的管理 不论在try代码块中是否发生了异常事件 finally块中的语句都会被执行 5 3 3异常的处理 2 异常的抛出在异常发生时 可以对它进行捕获 也可以将它继续抛出 例5 11 对异常进行抛出举例 程序如下 classCatchDemo2 Publicstaticvoidmain Stringargs throwsArithmeticException ArrayIndexOutOfBoundsException inta args length System out println na a intb 42 a intc 1 c 42 99 5 4创建自定义的异常 Java提供的一些异常有时候不能满足编程的需求 比如规定用户输入数据的范围在20到30之间 但是Java并没有这个方面的异常 这个时候就可以应用自定义的异常来规范化客户的数据输入 在Java中进行自定义异常时 自定义异常类必须是Throwable的直接或间接子类 下面的例子是关于自定义异常的 它通过继承Exception类而继承Throwable 即间接继承Throwable 5 4创建自定义的异常 例5 12 自定义异常举例 程序如下 classOutBoundsExceptionextendsException OutBoundsException Stringmes 调用超类的构造函数super mes classcheck StringChecktheNum intn throwsOutBoundsException IntegerN newInteger n if n 30 n 20 thrownewOutBoundsException thenumberisoutofbound elsereturn thenumber N toString isinthebound classTest 5 4创建自定义的异常 publicstaticvoidmain String args try checkc newcheck System out println 以下是合法的数据的报告 System out println c ChecktheNum 25 System out println 以下是非法的数据的报告 System out println c ChecktheNum 5 catch OutBoundsExceptione System out println e toString 运行结果如图5 13所示 5 4创建自定义的异常 图5 13运行结果 例5 12 5 5课后练习 1 填空题 1 声明接口的保留字是 2 类的声明 publicclassTestextendsAppletimplementsRunable 中 定义的类名是 其父类是 实现了 接口 这个类的源程序必须保存为 写出包括扩展名的文件名 2 选择题 1 接口是Java面向对象的实现机制之一 以下说法正确的是 A Java支持多重继承 一个类可以实现多个接口B Java只支持单重继承 一个类可以实现多个接口C Java只支持单重继承 一个类只可以实现一个接口D Java支持多重继承 但一个类只可以实现一个接口 2 关于接口的定义和实现 以下描述正确的是 A 接口定义中的方法都只有定义没有实现B 接口定义中的变量都必须写明final和staticC 如果一个接口由多个类来实现 则这些类在实现该接口中的方法时应采用统一的代码D 如果一个类实现一个接口 则必须实现该接口中的所有方法 但方法未必声明为public 5 5课后练习 3 判断题 1 对每个异常 只能进行捕获 2 接口中定义的方法可以是private型的 4 简答题 1 按照Java习惯 程序员应该如何组织和命名包 如何布局源文件 2 设置classpath参数的作用是什么 5 操作题 1 根据如图5 14所示的UML图设计完成编码TestAnimal java 使输出结果符合样例 Fishswimintheirtanksallday Fluffylikestoplaywithstring Spiderscatchfliesintheirwebstoeat Thisanimalwalkson8legs Thisanimalwalkson0legs Fish ofcourse can twalk theyswim 5 5课后练习 2 编写MyPoint java 定义点的数据结构为两个双精度数 x y 并重写toString方法 通过字符串连接运算 使输出点形式为 startpointisstart x y endpointisend x y 3 编写TestMyPoint java 实例化MyPoint为start和end 输出start和end的状态 4 编写方法distance 计算两点间的距离 5 5课后练习 图5 14UML图 Q A Thanks 第6章线程 时间 3次课 6学时 第6章线程 教学提示 计算机世界要想真正地反映现实世界 必须解决事情的同步问题 即解决程序实现多线程的问题 因此可编写有几条执行路径的程序 使得程序能够同时执行多个任务 借此实现多线程运行 Java语言的一大特点就是内置对多线程的支持 本章主要介绍 Java中的线程作用机制 线程的实现方法 线程的控制和线程的同步与死锁 第6章线程 6 1线程简介6 2线程的实现方法6 3线程的控制6 4Java的多线程实例6 5线程的同步与死锁6 6ThreadLocal问题6 7课后练习 6 1线程简介 6 1 1程序 进程和线程6 1 2线程的生命周期6 1 3线程的优先级及其调度6 1 4线程组 6 1线程简介 对于许多编程人员来说 线程并不是那么的陌生 但是在Java中 线程的作用机制又是如何工作的呢 本节将重点介绍Java中的线程作用机制 6 1 1程序 进程和线程 程序是由若干条语句组成的语句序列 是一段静态代码 进程是程序的一次动态执行过程 需要特别指出的是 进程不仅包括程序代码 还包括系统资源 即一个进程既包括其所要执行的指令 也包括执行指令所需的任何系统资源 如CPU 内存空间等 不同进程所占用的系统资源相对独立 6 1 1程序 进程和线程 线程又是一个抽象的概念 它包含了一个计算机执行传统程序时所做的每一件事情 线程是一种在CPU上调度的程序状态 它在某一瞬时看来只是计算过程的一个状态 一个进程中的所有线程共享该进程的状态 它们存储在相同的内存空间中 共享程序的代码和数据 所以当其中一个线程改变了进程的变量时 那么其他线程下次访的将是改变后的变量 多线程是指同一个应用程序中有多个顺序流同时执行 在一个程序中可以同时运行多个不同的线程来执行不同的任务 各个线程并行地完成各自的任务 浏览器就是一个典型的多线程例子 6 1 2线程的生命周期 每个Java程序都有一个默认的主线程 对于应用程序 主线程是main 方法执行的路径 图6 1说明线程的生命周期及其状态转换 6 1 2线程的生命周期 图6 1线程的状态转换 6 1 2线程的生命周期 从图6 1中可以看出 一个线程从创建到消亡的整个生命周期中 总是处于下面5个状态中的某个状态 1 新建状态通过new命令创建一个Thread类或其子类的线程对象时 该线程对象处于新建状态 创建一个新的线程对象可以用下面的语句实现 Threadthread newThread 该语句是最简单的创建线程的语句 但该语句创建的线程是一个空的线程对象 系统还未对这个线程分配任何资源 6 1 2线程的生命周期 2 就绪状态该状态又可称为可运行状态 处于新建状态的线程可通过调用start 方法启动该线程 Start 方法产生了线程运行需要的系统资源 启动后的线程将进入线程就绪队列排队等待CPU服务 此时线程已经具备了运行的条件 一旦它获得CPU等资源时就可以脱离创建它的主线程而独立运行 6 1 2线程的生命周期 3 运行状态当处于就绪状态的线程被调度并获得CPU资源时 使进入运行状态 每个线程对象都有一个重要的run 方法 run 方法定义了该线程的操作和功能 当线程对象被调度执行时 它将自动调用其run 方法并从第一条语句开始顺次执行 6 1 2线程的生命周期 4 阻塞状态又称不可运行状态 当发生下列情况之一时 线程就进入阻塞状态 1 等待输入输出操作完成 2 线程调用wait 方法等待一个条件变量 3 调用了该线程的sleep 休眠方法 4 调用了suspend 挂起方法 6 1 2线程的生命周期 5 消亡状态消亡状态又称死亡状态 当调用run 方法结束后 线程就进入消亡状态 这是线程的正常消亡 另外线程还可能被提前强制性消亡 不管何种情况 处于消亡状态的线程不具有继续运行的能力 6 1 3线程的优先级及其调度 线程被创建之后 每个Java线程的优先级都在Thread MIN PRIORITY 常量1 和Thread MAX PRIORITY 常量10 的范围之内 每个新建线程的默认优先级都为Thread NORM PRIORITY 常量5 可以用方法intgetPriority 来获得线程的优先级 同时也可以用方法voidsetPriority intp 在线程被创建后改变线程的优先级 一个线程将始终保持运行状态 直到出现下列情况 由于I O 或其他一些原因 而使该线程阻塞 调用sleep wait join或yield方法也将阻塞该线程 更高优先级的线程将抢占该线程 时间片的时间期满而退出运行状态或线程执行结束 6 1 3线程的优先级及其调度 例6 3 综合使用线程的方法来控制线程的工作举例 程序如下 一个实现Runnable接口的SimpleRunnable类classSimpleRunnableimplementsRunnable protectedStringmessage protectedintiterations publicSimpleRunnable Stringmsg intiter message msg iterations iter publicvoidrun for inti 0 i iterations i 1 System out println message try Thread sleep 100 catch InterruptedExceptione System out println e 6 1 3线程的优先级及其调度 ThreadExample类运行这个线程publicclassThreadExample publicstaticvoidmain Stringargs Threadt1 t2 t1 newThread newSimpleRunnable Thread1 10 t2 newThread newSimpleRunnable Thread2 15 System out println T1pis t1 getPriority System out println T2pis t2 getPriority t2 setPriority 7 System out println T2aftersetpis t2 getPriority t2 yield System out println T2afteryieldpis t2 getPriority t1 start t2 start 6 1 3线程的优先级及其调度 运行结果如下 T1pis 5T2pis 5T2aftersetpis 7T2afteryieldpis 7Thread2Thread1Thread2Thread1Thread2Thread1 6 1 3线程的优先级及其调度 Thread2Thread1Thread2Thread1Thread2Thread1Thread2Thread1Thread2Thread1Thread2Thread1Thread2Thread1Thread2Thread2Thread2Thread2Thread2 6 1 4线程组 线程组 ThreadGroup 允许把一组线程统一管理 例如 可以对一组线程同时调用interrupt 方法 中断这个组中所有线程的运行 创建线程组的构造方法为 ThreadGroup StringgroupName 线程组构造方法的字符串参数用来标识该线程组 并且它必须是独一无二的 线程组对象创建后 可以将各个线程添加到该线程组 在线程构造方法中指定所加入的线程组 Thread groupName threadName 6 1 4线程组 线程组下可以设子线程组 默认创建线程组将成为与当前线程同组的子线程组 当线程组中的某个线程由于一个异常而中止运行时 ThreadGroup类的uncaughtException Threadt Throwablee 方法将会打印这个异常的堆栈跟踪记录 6 2线程的实现方法 6 2 1继承Thread类6 2 2实现Runnable接口 6 2线程的实现方法 要使用多线程实现程序的流程控制 需要首先创建线程 生成线程实例 然后需要控制线程的调度 线程的创建分两步 定义线程体和创建线程对象 线程体决定线程的功能 它由run 方法实现 系统通过调用线程的run 方法实现线程的具体功能 Java中可通过继承Thread类或实现Runnable接口这两种途径来构造线程的run 方法 6 2 1继承Thread类 可通过创建Thread类的子类并重写其中的run 方法来定义线程体以实现线程的具体功能 然后创建该子类的对象以创建线程 Thread类在包java lang中 它定义了Java程序中一个线程需要拥有的属性和方法 如表6 1和表6 2所示 6 2 1继承Thread类 表6 1Thread类的属性 6 2 1继承Thread类 表6 2Thread类的构造方法和关键方法 6 2 2实现Runnable接口 另一种实现多线程的方法是实现Runnable接口 Runnable接口只定义了一个方法 run 方法 该方法是一个抽象方法 所有实现Runnable接口的类都必须具体实现这个方法 为它提供方法体并定义具体操作 Runnable接口中的run 方法与Thread类中的run 方法一样 是被系统自动识别执行的 6 2 2实现Runnable接口 通过实现Runnable接口实现多线程的一般步骤如下 1 创建实现Runnable接口的类ClassName 它的一般格式为 classClassNameimplementsRunnable publicvoidrun 编写代码 2 创建Runnable类ClassName的对象 一般格式为 ClassNameRunnableObject newClassName 3 用带有Runnable参数的Thread类构造方法创建线程对象 对象RunnableObject作为构造方法的参数 作为新建线程的目标对象为线程提供run 方法 如用表8 2中列出的构造方法Thread Runnabletarget 创建线程对象 ThreadThreadObject newThread RunnableObject 6 2 2实现Runnable接口 Thread类中除了上述构造方法带有Runnable参数外 还有下面3个构造方法也带有Runnable参数 Thread Runnabletarget Stringname Thread ThreadGroupgroup Runnabletarget Thread ThreadGroupgroup Runnabletarget Stringname 其中Runnable参数是一个实现了Runnable接口的某个类的对象 第2个和第3个方法的第一个参数是指明新创建的线程属于哪一个线程组 6 3线程的控制 6 3 1启动线程6 3 2线程休眠6 3 3中断线程 6 3线程的控制 父线程通过创建Thread对象并调用其start方法来启动子线程 start方法使该对象成为一个准备运行的新线程 第一次轮到该线程执行时 JVM就会调用run方法 线程可以处于以下5种状态的任何一种状态 新建 就绪 运行 阻塞和消亡状态 在Thread类里面 提供了一些控制多线程状态的方法 如表6 3所示 6 3线程的控制 表6 3线程的控制方法 6 3线程的控制 通过这些方法 线程的各个状态可以相互转换 转换的情况和Thread类的控制方法对线程的影响参见图6 3 下面详细讲解这些方法的用法 1 start 启动线程当Thread类的实例对象已经创建了 但没做任何事情时 就需要我们调用start 方法来启动线程 start 方法使Thread对象表示的虚拟CPU开始执行 也就是切换到就绪状态 在这之后 新线程开始执行可运行的run 方法 如果我们不是调用start 方法使线程执行 而是寄希望于直接调用run 方法来执行代码 实际上只是调用了一个名称为run 的方法 而不是一个线程 6 3线程的控制 1 start 2 stop 3 suspend 4 sleep 5 resume 6 yield 7 interrupt 8 等待处理资源图6 3线程的生命周期 6 3线程的控制 2 stop 停止线程stop 方法使线程停止 它激发死亡状态并且给出错误 但是 stop 方法只是Thread类的方法 当我们用Runnable接口创建线程时 我们是不能用stop 方法使线程停止的 3 suspend 暂停线程suspend 方法也只是Thread类的方法 调用这个方法可以使线程处于封锁状态 直至我们调用resume 方法来唤醒它 suspend 方法可以被自己和别的线程调用 通常是被别的线程调用 比如被鼠标单击事件处理程序调用 暂停后 该线程不能做任何事情 甚至没有办法调用resume 方法使自己重新启动 直至有别的线程调用resume 方法使之恢复 6 3线程的控制 4 sleep 暂停线程sleep 方法使控制流程暂停 在给定的 段时间内睡眠 所以特别适合需要在一定时间间隔内完成一个动作的线程 睡眠的时间由参数来决定 毫秒级和纳秒级分别对应两个方法 publicstaticvoidsleep longmillis throwsInterruptException 睡眠millis毫秒publicstaticvoidsleep longmillis intnanos throwsInterruptException 睡眠millis毫秒加上nanos纳秒 6 3线程的控制 5 resume 恢复线程调用resume 方法使线程重新启动 6 yield 使线程由运行状态转为就绪状态如果要编写多个合作线程 则可能浪费CPU时间 7 interrupt 唤醒正在睡眠的线程如果某个线程因调用了sleep 方法而暂停 可以调用interrupt 方法将之唤醒 后者用异常InterruptException来强制使sleep的调用提前返回 另外 还有join 方法 调用join 方法后线程暂停工作 并一直等待直到线程停止 6 3 1启动线程 例6 5 使用start方法启动线程 程序如下 classThreadBodyimplementsRunnable inti publicvoidrun try Thread currentThread sleep 100 System out println Thread currentThread getName ThreadBodytb newThreadBody Threadth newThread tb th start c
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 红酒评鉴考试题及答案
- 荔城市工匠评选活动方案
- 自助洗衣活动方案
- 海洋经济考试题及答案
- 贵族分类考试题及答案
- 估算法考试题及答案
- 幼儿园教学教案设计:安全过斑马线
- 钢琴作品考试题及答案
- 市场营销活动效果评估分析框架
- 公益投入参与行为承诺书5篇
- 自动化模具制造行业可行性分析报告
- 房颤心电图课件
- 工地拌和站试验室培训课件建筑土木工程
- 2024年卫生院“健康促进医院”创建工作总结样本(3篇)
- 副总经理招聘面试题与参考回答(某大型集团公司)2025年
- 餐饮4D管理培训资料
- 国庆节磨豆腐活动方案
- 七年级上册生命、生态、安全教案全册
- 峥嵘岁月 课件-2024-2025学年高中音乐人音版(2019) 必修 音乐鉴赏
- 《用户体验设计导论》
- 税务法律服务行业分析报告及未来三年行业发展报告
评论
0/150
提交评论